Add item_tree function to Component VTable

This commit is contained in:
Tobias Hunger 2022-03-14 14:22:32 +01:00 committed by Tobias Hunger
parent 106593eddc
commit ea684fa4de
4 changed files with 56 additions and 15 deletions

View file

@ -861,7 +861,7 @@ fn generate_item_tree(
visit_children_statements.extend([
"};".into(),
format!("auto self_rc = reinterpret_cast<const {}*>(component.instance)->self_weak.lock()->into_dyn();", item_tree_class_name),
"return slint::cbindgen_private::slint_visit_item_tree(&self_rc, item_tree() , index, order, visitor, dyn_visit);".to_owned(),
"return slint::cbindgen_private::slint_visit_item_tree(&self_rc, get_item_tree(component) , index, order, visitor, dyn_visit);".to_owned(),
]);
target_struct.members.push((
@ -874,6 +874,7 @@ fn generate_item_tree(
..Default::default()
}),
));
target_struct.members.push((
Access::Private,
Declaration::Function(Function {
@ -881,7 +882,20 @@ fn generate_item_tree(
signature: "(slint::private_api::ComponentRef component, uintptr_t index) -> slint::private_api::ItemRef".into(),
is_static: true,
statements: Some(vec![
"return slint::private_api::get_item_ref(component, item_tree(), item_array(), index);".to_owned(),
"return slint::private_api::get_item_ref(component, get_item_tree(component), item_array(), index);".to_owned(),
]),
..Default::default()
}),
));
target_struct.members.push((
Access::Private,
Declaration::Function(Function {
name: "get_item_tree".into(),
signature: "(slint::private_api::ComponentRef) -> slint::cbindgen_private::Slice<slint::private_api::ItemTreeNode>".into(),
is_static: true,
statements: Some(vec![
"return item_tree();".to_owned(),
]),
..Default::default()
}),
@ -895,7 +909,7 @@ fn generate_item_tree(
}) {
format!(
// that does not work when the parent is not a component with a ComponentVTable
//" *result = slint::private_api::parent_item(self->parent->self_weak.into_dyn(), self->parent->item_tree(), {});",
//" *result = slint::private_api::parent_item(self->parent->self_weak.into_dyn(), self->parent->get_item_tree(), {});",
"self->parent->self_weak.vtable()->parent_item(self->parent->self_weak.lock()->borrow(), {}, result);",
parent_index,
)
@ -914,7 +928,7 @@ fn generate_item_tree(
parent_item_from_parent_component,
" return;".into(),
"}".into(),
"*result = slint::private_api::parent_item(self->self_weak.into_dyn(), item_tree(), index);".into(),
"*result = slint::private_api::parent_item(self->self_weak.into_dyn(), get_item_tree(component), index);".into(),
]),
..Default::default()
}),
@ -981,7 +995,7 @@ fn generate_item_tree(
ty: "const slint::private_api::ComponentVTable".to_owned(),
name: format!("{}::static_vtable", item_tree_class_name),
init: Some(format!(
"{{ visit_children, get_item_ref, parent_item, layout_info, slint::private_api::drop_in_place<{}>, slint::private_api::dealloc }}",
"{{ visit_children, get_item_ref, get_item_tree, parent_item, layout_info, slint::private_api::drop_in_place<{}>, slint::private_api::dealloc }}",
item_tree_class_name)
),
..Default::default()

View file

@ -1058,7 +1058,7 @@ fn generate_item_tree(
-> slint::re_exports::VisitChildrenResult
{
use slint::re_exports::*;
return slint::re_exports::visit_item_tree(self, &VRcMapped::origin(&self.as_ref().self_weak.get().unwrap().upgrade().unwrap()), Self::item_tree(), index, order, visitor, visit_dynamic);
return slint::re_exports::visit_item_tree(self, &VRcMapped::origin(&self.as_ref().self_weak.get().unwrap().upgrade().unwrap()), self.get_item_tree().as_slice(), index, order, visitor, visit_dynamic);
#[allow(unused)]
fn visit_dynamic(_self: ::core::pin::Pin<&#inner_component_id>, order: slint::re_exports::TraversalOrder, visitor: ItemVisitorRefMut, dyn_index: usize) -> VisitChildrenResult {
_self.visit_dynamic_children(dyn_index, order, visitor)
@ -1066,7 +1066,7 @@ fn generate_item_tree(
}
fn get_item_ref(self: ::core::pin::Pin<&Self>, index: usize) -> ::core::pin::Pin<ItemRef> {
match &Self::item_tree()[index] {
match &self.get_item_tree().as_slice()[index] {
ItemTreeNode::Item { item_array_index, .. } => {
Self::item_array()[*item_array_index as usize].apply_pin(self)
}
@ -1075,6 +1075,12 @@ fn generate_item_tree(
}
}
fn get_item_tree(
self: ::core::pin::Pin<&Self>) -> slint::re_exports::Slice<slint::re_exports::ItemTreeNode>
{
Self::item_tree().into()
}
fn parent_item(self: ::core::pin::Pin<&Self>, index: usize, result: &mut slint::re_exports::ItemWeak) {
if index == 0 {
#(
@ -1084,7 +1090,7 @@ fn generate_item_tree(
)*
return;
}
let parent_index = Self::item_tree()[index].parent_index();
let parent_index = self.get_item_tree().as_slice()[index].parent_index();
let self_rc = slint::re_exports::VRcMapped::origin(&self.self_weak.get().unwrap().upgrade().unwrap());
*result = ItemRc::new(self_rc, parent_index).downgrade();
}

View file

@ -5,9 +5,10 @@
//! This module contains the basic datastructures that are exposed to the C API
use crate::item_tree::{ItemVisitorVTable, TraversalOrder, VisitChildrenResult};
use crate::item_tree::{ItemTreeNode, ItemVisitorVTable, TraversalOrder, VisitChildrenResult};
use crate::items::{ItemVTable, ItemWeak};
use crate::layout::{LayoutInfo, Orientation};
use crate::slice::Slice;
use crate::window::WindowRc;
use vtable::*;
@ -31,6 +32,11 @@ pub struct ComponentVTable {
index: usize,
) -> core::pin::Pin<VRef<ItemVTable>>,
/// Return the item tree that is defined by this `Component`.
/// The return value is an item weak because it can be null if there is no parent.
/// And the return value is passed by &mut because ItemWeak has a destructor
pub get_item_tree: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> Slice<ItemTreeNode>,
/// Return the parent item.
/// The return value is an item weak because it can be null if there is no parent.
/// And the return value is passed by &mut because ItemWeak has a destructor
@ -82,7 +88,6 @@ pub(crate) mod ffi {
#![allow(unsafe_code)]
use super::*;
use crate::slice::Slice;
/// Call init() on the ItemVTable of each item in the item array.
#[no_mangle]

View file

@ -22,6 +22,7 @@ use i_slint_core::model::RepeatedComponent;
use i_slint_core::model::Repeater;
use i_slint_core::properties::InterpolatedPropertyValue;
use i_slint_core::rtti::{self, AnimatedBindingKind, FieldOffset, PropertyInfo};
use i_slint_core::slice::Slice;
use i_slint_core::window::{WindowHandleAccess, WindowRc};
use i_slint_core::{Brush, Color, Property, SharedString, SharedVector};
use std::collections::BTreeMap;
@ -161,12 +162,18 @@ impl Component for ErasedComponentBox {
fn layout_info(self: Pin<&Self>, orientation: Orientation) -> i_slint_core::layout::LayoutInfo {
self.borrow().as_ref().layout_info(orientation)
}
fn get_item_tree(self: Pin<&Self>) -> Slice<ItemTreeNode> {
get_item_tree(self.get_ref().borrow())
}
fn get_item_ref(self: Pin<&Self>, index: usize) -> Pin<ItemRef> {
// We're having difficulties transferring the lifetime to a pinned reference
// to the other ComponentVTable with the same life time. So skip the vtable
// indirection and call our implementation directly.
unsafe { get_item_ref(self.get_ref().borrow(), index) }
}
fn parent_item(self: Pin<&Self>, index: usize, result: &mut ItemWeak) {
self.borrow().as_ref().parent_item(index, result)
}
@ -582,7 +589,7 @@ extern "C" fn visit_children_item(
i_slint_core::item_tree::visit_item_tree(
instance_ref.instance,
&vtable::VRc::into_dyn(comp_rc),
instance_ref.component_type.item_tree.as_slice(),
get_item_tree(component).as_slice(),
index,
order,
v,
@ -1021,6 +1028,7 @@ pub(crate) fn generate_component<'id>(
visit_children_item,
layout_info,
get_item_ref,
get_item_tree,
parent_item,
drop_in_place,
dealloc,
@ -1495,10 +1503,11 @@ extern "C" fn layout_info(component: ComponentRefPin, orientation: Orientation)
}
unsafe extern "C" fn get_item_ref(component: ComponentRefPin, index: usize) -> Pin<ItemRef> {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
match &instance_ref.component_type.item_tree.as_slice()[index] {
let tree = get_item_tree(component);
match &tree[index] {
ItemTreeNode::Item { item_array_index, .. } => {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
core::mem::transmute::<Pin<ItemRef>, Pin<ItemRef>>(
instance_ref.component_type.item_array[*item_array_index as usize]
.apply_pin(instance_ref.instance),
@ -1508,6 +1517,13 @@ unsafe extern "C" fn get_item_ref(component: ComponentRefPin, index: usize) -> P
}
}
extern "C" fn get_item_tree(component: ComponentRefPin) -> Slice<ItemTreeNode> {
generativity::make_guard!(guard);
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
let tree = instance_ref.component_type.item_tree.as_slice();
unsafe { core::mem::transmute::<&[ItemTreeNode], &[ItemTreeNode]>(tree) }.into()
}
unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize, result: &mut ItemWeak) {
generativity::make_guard!(guard);
let instance_ref = InstanceRef::from_pin_ref(component, guard);
@ -1537,7 +1553,7 @@ unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize, resul
}
return;
}
let parent_index = instance_ref.component_type.item_tree.as_slice()[index].parent_index();
let parent_index = get_item_tree(component)[index].parent_index();
let self_rc = instance_ref.self_weak().get().unwrap().clone().into_dyn().upgrade().unwrap();
*result = ItemRc::new(self_rc, parent_index).downgrade();
}