mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-02 12:58:23 +00:00
Component: Add information to stich together ItemTrees
Add accessors to the information necessary to stitch together the Component-wide ItemTrees (which include DynamicNodes) into one logical tree of Items.
This commit is contained in:
parent
c1bb22bd00
commit
ee68716d07
8 changed files with 368 additions and 17 deletions
|
|
@ -42,10 +42,12 @@ namespace slint {
|
||||||
namespace private_api {
|
namespace private_api {
|
||||||
using cbindgen_private::ComponentVTable;
|
using cbindgen_private::ComponentVTable;
|
||||||
using cbindgen_private::ItemVTable;
|
using cbindgen_private::ItemVTable;
|
||||||
|
using ComponentRc = vtable::VRc<private_api::ComponentVTable>;
|
||||||
using ComponentRef = vtable::VRef<private_api::ComponentVTable>;
|
using ComponentRef = vtable::VRef<private_api::ComponentVTable>;
|
||||||
|
using IndexRange = cbindgen_private::IndexRange;
|
||||||
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::ComponentRc;
|
using cbindgen_private::ComponentWeak;
|
||||||
using cbindgen_private::ItemWeak;
|
using cbindgen_private::ItemWeak;
|
||||||
using cbindgen_private::TraversalOrder;
|
using cbindgen_private::TraversalOrder;
|
||||||
}
|
}
|
||||||
|
|
@ -846,6 +848,16 @@ public:
|
||||||
return { &C::static_vtable, const_cast<C *>(&(**x.ptr)) };
|
return { &C::static_vtable, const_cast<C *>(&(**x.ptr)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void component_at(int i, vtable::VWeak<private_api::ComponentVTable> *result) const
|
||||||
|
{
|
||||||
|
const auto &x = inner->data.at(i);
|
||||||
|
*result = vtable::VWeak<private_api::ComponentVTable>{x.ptr->into_dyn()};
|
||||||
|
}
|
||||||
|
|
||||||
|
private_api::IndexRange index_range() const {
|
||||||
|
return private_api::IndexRange { 0, inner->data.size() };
|
||||||
|
}
|
||||||
|
|
||||||
float compute_layout_listview(const private_api::Property<float> *viewport_width,
|
float compute_layout_listview(const private_api::Property<float> *viewport_width,
|
||||||
float listview_width) const
|
float listview_width) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore buildrs
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
# Slint
|
# Slint
|
||||||
|
|
||||||
|
|
@ -283,7 +285,7 @@ pub mod re_exports {
|
||||||
pub use i_slint_core::callbacks::Callback;
|
pub use i_slint_core::callbacks::Callback;
|
||||||
pub use i_slint_core::component::{
|
pub use i_slint_core::component::{
|
||||||
free_component_item_graphics_resources, init_component_items, Component, ComponentRefPin,
|
free_component_item_graphics_resources, init_component_items, Component, ComponentRefPin,
|
||||||
ComponentVTable,
|
ComponentVTable, ComponentWeak, IndexRange,
|
||||||
};
|
};
|
||||||
pub use i_slint_core::graphics::*;
|
pub use i_slint_core::graphics::*;
|
||||||
pub use i_slint_core::input::{
|
pub use i_slint_core::input::{
|
||||||
|
|
|
||||||
|
|
@ -848,15 +848,25 @@ fn generate_item_tree(
|
||||||
let mut visit_children_statements = vec![
|
let mut visit_children_statements = vec![
|
||||||
"static const auto dyn_visit = [] (const uint8_t *base, [[maybe_unused]] slint::private_api::TraversalOrder order, [[maybe_unused]] slint::private_api::ItemVisitorRefMut visitor, [[maybe_unused]] uintptr_t dyn_index) -> uint64_t {".to_owned(),
|
"static const auto dyn_visit = [] (const uint8_t *base, [[maybe_unused]] slint::private_api::TraversalOrder order, [[maybe_unused]] slint::private_api::ItemVisitorRefMut visitor, [[maybe_unused]] uintptr_t dyn_index) -> uint64_t {".to_owned(),
|
||||||
format!(" [[maybe_unused]] auto self = reinterpret_cast<const {}*>(base);", item_tree_class_name)];
|
format!(" [[maybe_unused]] auto self = reinterpret_cast<const {}*>(base);", item_tree_class_name)];
|
||||||
|
let mut subtree_range_statement = vec![" std::abort();".into()];
|
||||||
|
let mut subtree_component_statement = vec![" std::abort();".into()];
|
||||||
|
|
||||||
if target_struct.members.iter().any(|(_, declaration)| {
|
if target_struct.members.iter().any(|(_, declaration)| {
|
||||||
matches!(&declaration, Declaration::Function(func @ Function { .. }) if func.name == "visit_dynamic_children")
|
matches!(&declaration, Declaration::Function(func @ Function { .. }) if func.name == "visit_dynamic_children")
|
||||||
}) {
|
}) {
|
||||||
visit_children_statements
|
visit_children_statements
|
||||||
.push(" return self->visit_dynamic_children(dyn_index, order, visitor);".into());
|
.push(" return self->visit_dynamic_children(dyn_index, order, visitor);".into());
|
||||||
|
subtree_range_statement = vec![
|
||||||
|
format!("auto self = reinterpret_cast<const {}*>(component.instance);", item_tree_class_name),
|
||||||
|
"return self->subtree_range(dyn_index);".to_owned(),
|
||||||
|
];
|
||||||
|
subtree_component_statement = vec![
|
||||||
|
format!("auto self = reinterpret_cast<const {}*>(component.instance);", item_tree_class_name),
|
||||||
|
"self->subtree_component(dyn_index, subtree_index, result);".to_owned(),
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
visit_children_statements.push(" std::abort();".into());
|
visit_children_statements.push(" std::abort();".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
visit_children_statements.extend([
|
visit_children_statements.extend([
|
||||||
"};".into(),
|
"};".into(),
|
||||||
|
|
@ -888,6 +898,28 @@ fn generate_item_tree(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
target_struct.members.push((
|
||||||
|
Access::Private,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "get_subtree_range".into(),
|
||||||
|
signature: "([[maybe_unused]] slint::private_api::ComponentRef component, [[maybe_unused]] uintptr_t dyn_index) -> slint::private_api::IndexRange".into(),
|
||||||
|
is_static: true,
|
||||||
|
statements: Some(subtree_range_statement),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
|
target_struct.members.push((
|
||||||
|
Access::Private,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "get_subtree_component".into(),
|
||||||
|
signature: "([[maybe_unused]] slint::private_api::ComponentRef component, [[maybe_unused]] uintptr_t dyn_index, [[maybe_unused]] uintptr_t subtree_index, [[maybe_unused]] slint::private_api::ComponentWeak *result) -> void".into(),
|
||||||
|
is_static: true,
|
||||||
|
statements: Some(subtree_component_statement),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
target_struct.members.push((
|
target_struct.members.push((
|
||||||
Access::Private,
|
Access::Private,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
|
|
@ -910,7 +942,7 @@ fn generate_item_tree(
|
||||||
format!(
|
format!(
|
||||||
// that does not work when the parent is not a component with a ComponentVTable
|
// 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->get_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);",
|
"*result = {{ self->parent->self_weak, {} }};",
|
||||||
parent_index,
|
parent_index,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -934,6 +966,17 @@ fn generate_item_tree(
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
target_struct.members.push((
|
||||||
|
Access::Private,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "subtree_index".into(),
|
||||||
|
signature: "(slint::private_api::ComponentRef /* component */) -> uintptr_t".into(),
|
||||||
|
is_static: true,
|
||||||
|
statements: Some(vec!["/* unimplemented! */".to_owned(), "return 0;".into()]),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
|
||||||
target_struct.members.push((
|
target_struct.members.push((
|
||||||
Access::Private,
|
Access::Private,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
|
|
@ -995,7 +1038,7 @@ fn generate_item_tree(
|
||||||
ty: "const slint::private_api::ComponentVTable".to_owned(),
|
ty: "const slint::private_api::ComponentVTable".to_owned(),
|
||||||
name: format!("{}::static_vtable", item_tree_class_name),
|
name: format!("{}::static_vtable", item_tree_class_name),
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
"{{ visit_children, get_item_ref, get_item_tree, parent_item, layout_info, slint::private_api::drop_in_place<{}>, slint::private_api::dealloc }}",
|
"{{ visit_children, get_item_ref, get_subtree_range, get_subtree_component, get_item_tree, parent_item, subtree_index, layout_info, slint::private_api::drop_in_place<{}>, slint::private_api::dealloc }}",
|
||||||
item_tree_class_name)
|
item_tree_class_name)
|
||||||
),
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -1181,6 +1224,8 @@ fn generate_sub_component(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut children_visitor_cases = Vec::new();
|
let mut children_visitor_cases = Vec::new();
|
||||||
|
let mut subtrees_ranges_cases = Vec::new();
|
||||||
|
let mut subtrees_components_cases = Vec::new();
|
||||||
|
|
||||||
let mut subcomponent_init_code = Vec::new();
|
let mut subcomponent_init_code = Vec::new();
|
||||||
for sub in &component.sub_components {
|
for sub in &component.sub_components {
|
||||||
|
|
@ -1223,6 +1268,23 @@ fn generate_sub_component(
|
||||||
id = field_name,
|
id = field_name,
|
||||||
base = repeater_offset,
|
base = repeater_offset,
|
||||||
));
|
));
|
||||||
|
subtrees_ranges_cases.push(format!(
|
||||||
|
"\n {case_code} {{
|
||||||
|
return self->{id}.subtree_range(dyn_index - {base});
|
||||||
|
}}",
|
||||||
|
case_code = case_code,
|
||||||
|
id = field_name,
|
||||||
|
base = repeater_offset,
|
||||||
|
));
|
||||||
|
subtrees_components_cases.push(format!(
|
||||||
|
"\n {case_code} {{
|
||||||
|
self->{id}.subtree_component(dyn_index - {base}, subtree_index, result);
|
||||||
|
return;
|
||||||
|
}}",
|
||||||
|
case_code = case_code,
|
||||||
|
id = field_name,
|
||||||
|
base = repeater_offset,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
target_struct.members.push((
|
target_struct.members.push((
|
||||||
|
|
@ -1321,6 +1383,25 @@ fn generate_sub_component(
|
||||||
i = idx,
|
i = idx,
|
||||||
e_u = ensure_updated,
|
e_u = ensure_updated,
|
||||||
));
|
));
|
||||||
|
subtrees_ranges_cases.push(format!(
|
||||||
|
"\n case {i}: {{
|
||||||
|
{e_u}
|
||||||
|
return self->{id}.index_range();
|
||||||
|
}}",
|
||||||
|
i = idx,
|
||||||
|
e_u = ensure_updated,
|
||||||
|
id = repeater_id,
|
||||||
|
));
|
||||||
|
subtrees_components_cases.push(format!(
|
||||||
|
"\n case {i}: {{
|
||||||
|
{e_u}
|
||||||
|
self->{id}.component_at(subtree_index, result);
|
||||||
|
return;
|
||||||
|
}}",
|
||||||
|
i = idx,
|
||||||
|
e_u = ensure_updated,
|
||||||
|
id = repeater_id,
|
||||||
|
));
|
||||||
|
|
||||||
target_struct.members.push((
|
target_struct.members.push((
|
||||||
Access::Private,
|
Access::Private,
|
||||||
|
|
@ -1382,6 +1463,32 @@ fn generate_sub_component(
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
target_struct.members.push((
|
||||||
|
field_access,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "subtree_range".into(),
|
||||||
|
signature: "(uintptr_t dyn_index) const -> slint::private_api::IndexRange".into(),
|
||||||
|
statements: Some(vec![
|
||||||
|
"[[maybe_unused]] auto self = this;".to_owned(),
|
||||||
|
format!(" switch(dyn_index) {{ {} }};", subtrees_ranges_cases.join("")),
|
||||||
|
" std::abort();".to_owned(),
|
||||||
|
]),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
target_struct.members.push((
|
||||||
|
field_access,
|
||||||
|
Declaration::Function(Function {
|
||||||
|
name: "subtree_component".into(),
|
||||||
|
signature: "(uintptr_t dyn_index, [[maybe_unused]] uintptr_t subtree_index, [[maybe_unused]] slint::private_api::ComponentWeak *result) const -> void".into(),
|
||||||
|
statements: Some(vec![
|
||||||
|
"[[maybe_unused]] auto self = this;".to_owned(),
|
||||||
|
format!(" switch(dyn_index) {{ {} }};", subtrees_components_cases.join("")),
|
||||||
|
" std::abort();".to_owned(),
|
||||||
|
]),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore conv powf punct
|
||||||
|
|
||||||
/*! module for the Rust code generator
|
/*! module for the Rust code generator
|
||||||
|
|
||||||
Some convention used in the generated code:
|
Some convention used in the generated code:
|
||||||
|
|
@ -117,7 +119,7 @@ pub fn generate(doc: &Document) -> TokenStream {
|
||||||
let sub_compos = llr
|
let sub_compos = llr
|
||||||
.sub_components
|
.sub_components
|
||||||
.iter()
|
.iter()
|
||||||
.map(|sub_compo| generate_sub_component(sub_compo, &llr, None, quote!()))
|
.map(|sub_compo| generate_sub_component(sub_compo, &llr, None, quote!(), None))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let compo = generate_public_component(&llr);
|
let compo = generate_public_component(&llr);
|
||||||
|
|
@ -243,7 +245,7 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
||||||
let global_container_id = format_ident!("Globals_{}", public_component_id);
|
let global_container_id = format_ident!("Globals_{}", public_component_id);
|
||||||
|
|
||||||
let component =
|
let component =
|
||||||
generate_item_tree(&llr.item_tree, llr, None, quote!(globals: #global_container_id));
|
generate_item_tree(&llr.item_tree, llr, None, quote!(globals: #global_container_id), None);
|
||||||
|
|
||||||
let ctx = EvaluationContext {
|
let ctx = EvaluationContext {
|
||||||
public_component: llr,
|
public_component: llr,
|
||||||
|
|
@ -515,6 +517,7 @@ fn generate_sub_component(
|
||||||
root: &llr::PublicComponent,
|
root: &llr::PublicComponent,
|
||||||
parent_ctx: Option<ParentCtx>,
|
parent_ctx: Option<ParentCtx>,
|
||||||
extra_fields: TokenStream,
|
extra_fields: TokenStream,
|
||||||
|
index_property: Option<llr::PropertyIndex>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let inner_component_id = inner_component_id(component);
|
let inner_component_id = inner_component_id(component);
|
||||||
|
|
||||||
|
|
@ -527,7 +530,9 @@ fn generate_sub_component(
|
||||||
let mut extra_components = component
|
let mut extra_components = component
|
||||||
.popup_windows
|
.popup_windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| generate_item_tree(c, root, Some(ParentCtx::new(&ctx, None)), quote!()))
|
.map(|c| {
|
||||||
|
generate_item_tree(c, root, Some(ParentCtx::new(&ctx, None)), quote!(), index_property)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut declared_property_vars = vec![];
|
let mut declared_property_vars = vec![];
|
||||||
|
|
@ -592,6 +597,8 @@ fn generate_sub_component(
|
||||||
let mut repeated_element_names: Vec<Ident> = vec![];
|
let mut repeated_element_names: Vec<Ident> = vec![];
|
||||||
let mut repeated_visit_branch: Vec<TokenStream> = vec![];
|
let mut repeated_visit_branch: Vec<TokenStream> = vec![];
|
||||||
let mut repeated_element_components: Vec<Ident> = vec![];
|
let mut repeated_element_components: Vec<Ident> = vec![];
|
||||||
|
let mut repeated_subtree_ranges: Vec<TokenStream> = vec![];
|
||||||
|
let mut repeated_subtree_components: Vec<TokenStream> = vec![];
|
||||||
|
|
||||||
for (idx, repeated) in component.repeated.iter().enumerate() {
|
for (idx, repeated) in component.repeated.iter().enumerate() {
|
||||||
extra_components.push(generate_repeated_component(
|
extra_components.push(generate_repeated_component(
|
||||||
|
|
@ -643,6 +650,19 @@ fn generate_sub_component(
|
||||||
_self.#repeater_id.visit(order, visitor)
|
_self.#repeater_id.visit(order, visitor)
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
repeated_subtree_ranges.push(quote!(
|
||||||
|
#idx => {
|
||||||
|
#ensure_updated
|
||||||
|
let (start, end) = _self.#repeater_id.range();
|
||||||
|
slint::re_exports::IndexRange { start, end }
|
||||||
|
}
|
||||||
|
));
|
||||||
|
repeated_subtree_components.push(quote!(
|
||||||
|
#idx => {
|
||||||
|
#ensure_updated
|
||||||
|
*result = vtable::VRc::downgrade(&vtable::VRc::into_dyn(_self.#repeater_id.component_at(subtree_index).unwrap()))
|
||||||
|
}
|
||||||
|
));
|
||||||
repeated_element_names.push(repeater_id);
|
repeated_element_names.push(repeater_id);
|
||||||
repeated_element_components.push(rep_inner_component_id);
|
repeated_element_components.push(rep_inner_component_id);
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +707,16 @@ fn generate_sub_component(
|
||||||
#sub_compo_field.apply_pin(_self).visit_dynamic_children(dyn_index - #repeater_offset, order, visitor)
|
#sub_compo_field.apply_pin(_self).visit_dynamic_children(dyn_index - #repeater_offset, order, visitor)
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
repeated_subtree_ranges.push(quote!(
|
||||||
|
#repeater_offset..=#last_repeater => {
|
||||||
|
#sub_compo_field.apply_pin(_self).subtree_range(dyn_index - #repeater_offset)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
repeated_subtree_components.push(quote!(
|
||||||
|
#repeater_offset..=#last_repeater => {
|
||||||
|
#sub_compo_field.apply_pin(_self).subtree_component(dyn_index - #repeater_offset, subtree_index, result)
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
sub_component_names.push(field_name);
|
sub_component_names.push(field_name);
|
||||||
|
|
@ -736,6 +766,18 @@ fn generate_sub_component(
|
||||||
let visibility =
|
let visibility =
|
||||||
core::ptr::eq(&root.item_tree.root as *const _, component as *const _).then(|| quote!(pub));
|
core::ptr::eq(&root.item_tree.root as *const _, component as *const _).then(|| quote!(pub));
|
||||||
|
|
||||||
|
let access_prop = |&property_index| {
|
||||||
|
access_member(
|
||||||
|
&llr::PropertyReference::Local { sub_component_path: vec![], property_index },
|
||||||
|
&ctx,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let prop = index_property.iter().map(access_prop);
|
||||||
|
let mut subtree_index_function = quote!(#(#prop.get() as usize)*);
|
||||||
|
if subtree_index_function.is_empty() {
|
||||||
|
subtree_index_function = quote!(core::usize::MAX);
|
||||||
|
}
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[derive(slint::re_exports::FieldOffsets, Default)]
|
#[derive(slint::re_exports::FieldOffsets, Default)]
|
||||||
#[const_field_offset(slint::re_exports::const_field_offset)]
|
#[const_field_offset(slint::re_exports::const_field_offset)]
|
||||||
|
|
@ -796,6 +838,33 @@ fn generate_sub_component(
|
||||||
slint::re_exports::Orientation::Vertical => #layout_info_v,
|
slint::re_exports::Orientation::Vertical => #layout_info_v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn subtree_range(self: ::core::pin::Pin<&Self>, dyn_index: usize) -> slint::re_exports::IndexRange {
|
||||||
|
#![allow(unused)]
|
||||||
|
use slint::re_exports::*;
|
||||||
|
let _self = self;
|
||||||
|
match dyn_index {
|
||||||
|
#(#repeated_subtree_ranges)*
|
||||||
|
_ => panic!("invalid dyn_index {}", dyn_index),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subtree_component(self: ::core::pin::Pin<&Self>, dyn_index: usize, subtree_index: usize, result: &mut slint::re_exports::ComponentWeak) {
|
||||||
|
#![allow(unused)]
|
||||||
|
use slint::re_exports::*;
|
||||||
|
let _self = self;
|
||||||
|
match dyn_index {
|
||||||
|
#(#repeated_subtree_components)*
|
||||||
|
_ => panic!("invalid dyn_index {}", dyn_index),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_property(self: ::core::pin::Pin<&Self>) -> usize {
|
||||||
|
#![allow(unused)]
|
||||||
|
use slint::re_exports::*;
|
||||||
|
let _self = self;
|
||||||
|
#subtree_index_function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#extra_components)*
|
#(#extra_components)*
|
||||||
|
|
@ -923,8 +992,15 @@ fn generate_item_tree(
|
||||||
root: &llr::PublicComponent,
|
root: &llr::PublicComponent,
|
||||||
parent_ctx: Option<ParentCtx>,
|
parent_ctx: Option<ParentCtx>,
|
||||||
extra_fields: TokenStream,
|
extra_fields: TokenStream,
|
||||||
|
index_property: Option<llr::PropertyIndex>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let sub_comp = generate_sub_component(&sub_tree.root, root, parent_ctx.clone(), extra_fields);
|
let sub_comp = generate_sub_component(
|
||||||
|
&sub_tree.root,
|
||||||
|
root,
|
||||||
|
parent_ctx.clone(),
|
||||||
|
extra_fields,
|
||||||
|
index_property,
|
||||||
|
);
|
||||||
let inner_component_id = self::inner_component_id(&sub_tree.root);
|
let inner_component_id = self::inner_component_id(&sub_tree.root);
|
||||||
let parent_component_type = parent_ctx.iter().map(|parent| {
|
let parent_component_type = parent_ctx.iter().map(|parent| {
|
||||||
let parent_component_id = self::inner_component_id(parent.ctx.current_sub_component.unwrap());
|
let parent_component_id = self::inner_component_id(parent.ctx.current_sub_component.unwrap());
|
||||||
|
|
@ -1077,11 +1153,29 @@ fn generate_item_tree(
|
||||||
Self::item_tree().into()
|
Self::item_tree().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_subtree_range(
|
||||||
|
self: ::core::pin::Pin<&Self>, index: usize) -> slint::re_exports::IndexRange
|
||||||
|
{
|
||||||
|
self.subtree_range(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_subtree_component(
|
||||||
|
self: ::core::pin::Pin<&Self>, index: usize, subtree_index: usize, result: &mut slint::re_exports::ComponentWeak)
|
||||||
|
{
|
||||||
|
self.subtree_component(index, subtree_index, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subtree_index(
|
||||||
|
self: ::core::pin::Pin<&Self>) -> usize
|
||||||
|
{
|
||||||
|
self.index_property()
|
||||||
|
}
|
||||||
|
|
||||||
fn parent_item(self: ::core::pin::Pin<&Self>, index: usize, result: &mut slint::re_exports::ItemWeak) {
|
fn parent_item(self: ::core::pin::Pin<&Self>, index: usize, result: &mut slint::re_exports::ItemWeak) {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
#(
|
#(
|
||||||
if let Some(parent) = self.parent.clone().upgrade().map(|sc| VRcMapped::origin(&sc)) {
|
if let Some(parent) = self.parent.clone().upgrade().map(|sc| VRcMapped::origin(&sc)) {
|
||||||
*result = slint::re_exports::ItemRc::new(parent, #parent_item_index).parent_item();
|
*result = slint::re_exports::ItemRc::new(parent, #parent_item_index).downgrade();
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
return;
|
return;
|
||||||
|
|
@ -1105,8 +1199,13 @@ fn generate_repeated_component(
|
||||||
root: &llr::PublicComponent,
|
root: &llr::PublicComponent,
|
||||||
parent_ctx: ParentCtx,
|
parent_ctx: ParentCtx,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let component =
|
let component = generate_item_tree(
|
||||||
generate_item_tree(&repeated.sub_tree, root, Some(parent_ctx.clone()), quote!());
|
&repeated.sub_tree,
|
||||||
|
root,
|
||||||
|
Some(parent_ctx.clone()),
|
||||||
|
quote!(),
|
||||||
|
repeated.index_prop,
|
||||||
|
);
|
||||||
|
|
||||||
let ctx = EvaluationContext {
|
let ctx = EvaluationContext {
|
||||||
public_component: root,
|
public_component: root,
|
||||||
|
|
@ -1120,7 +1219,7 @@ fn generate_repeated_component(
|
||||||
let inner_component_id = self::inner_component_id(&repeated.sub_tree.root);
|
let inner_component_id = self::inner_component_id(&repeated.sub_tree.root);
|
||||||
|
|
||||||
// let rep_inner_component_id = self::inner_component_id(&repeated.sub_tree.root.name);
|
// let rep_inner_component_id = self::inner_component_id(&repeated.sub_tree.root.name);
|
||||||
// let inner_component_id = self::inner_component_id(&parent_compo);
|
// let inner_component_id = self::inner_component_id(&parent_compo);
|
||||||
|
|
||||||
let extra_fn = if let Some(listview) = &repeated.listview {
|
let extra_fn = if let Some(listview) = &repeated.listview {
|
||||||
let p_y = access_member(&listview.prop_y, &ctx);
|
let p_y = access_member(&listview.prop_y, &ctx);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore dealloc
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
//! This module contains the basic datastructures that are exposed to the C API
|
//! This module contains the basic datastructures that are exposed to the C API
|
||||||
|
|
@ -12,6 +14,15 @@ use crate::slice::Slice;
|
||||||
use crate::window::WindowRc;
|
use crate::window::WindowRc;
|
||||||
use vtable::*;
|
use vtable::*;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
/// A range of indices
|
||||||
|
pub struct IndexRange {
|
||||||
|
/// Start index
|
||||||
|
pub start: usize,
|
||||||
|
/// Index one past the last index
|
||||||
|
pub end: usize,
|
||||||
|
}
|
||||||
|
|
||||||
/// A Component is representing an unit that is allocated together
|
/// A Component is representing an unit that is allocated together
|
||||||
#[vtable]
|
#[vtable]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -32,17 +43,35 @@ pub struct ComponentVTable {
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> core::pin::Pin<VRef<ItemVTable>>,
|
) -> core::pin::Pin<VRef<ItemVTable>>,
|
||||||
|
|
||||||
|
/// Return the range of indices below the dynamic `ItemTreeNode` at `index`
|
||||||
|
pub get_subtree_range:
|
||||||
|
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, index: usize) -> IndexRange,
|
||||||
|
|
||||||
|
/// Return the `ComponentRc` at `subindex` below the dynamic `ItemTreeNode` at `index`
|
||||||
|
pub get_subtree_component: extern "C" fn(
|
||||||
|
core::pin::Pin<VRef<ComponentVTable>>,
|
||||||
|
index: usize,
|
||||||
|
subindex: usize,
|
||||||
|
result: &mut vtable::VWeak<ComponentVTable, Dyn>,
|
||||||
|
),
|
||||||
|
|
||||||
/// Return the item tree that is defined by this `Component`.
|
/// 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.
|
/// 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
|
/// 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>,
|
pub get_item_tree: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> Slice<ItemTreeNode>,
|
||||||
|
|
||||||
|
// FIXME: This does return an invalid ItemWeak now that points to the parent repeater!
|
||||||
|
// FIXME: Get rid of the index and make this always return the "Item" that connects this component
|
||||||
|
// to its parent-component?
|
||||||
/// Return the parent item.
|
/// Return the parent item.
|
||||||
/// The return value is an item weak because it can be null if there is no parent.
|
/// 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
|
/// And the return value is passed by &mut because ItemWeak has a destructor
|
||||||
pub parent_item:
|
pub parent_item:
|
||||||
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, index: usize, result: &mut ItemWeak),
|
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, index: usize, result: &mut ItemWeak),
|
||||||
|
|
||||||
|
/// Return the index of the current subtree or usize::MAX if this is not a subtree
|
||||||
|
pub subtree_index: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> usize,
|
||||||
|
|
||||||
/// Returns the layout info for this component
|
/// Returns the layout info for this component
|
||||||
pub layout_info:
|
pub layout_info:
|
||||||
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, Orientation) -> LayoutInfo,
|
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, Orientation) -> LayoutInfo,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore dealloc nesw
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
This module contains the builtin items, either in this file or in sub-modules.
|
This module contains the builtin items, either in this file or in sub-modules.
|
||||||
|
|
||||||
|
|
@ -177,6 +179,7 @@ impl ItemRc {
|
||||||
pub fn new(component: vtable::VRc<ComponentVTable>, index: usize) -> Self {
|
pub fn new(component: vtable::VRc<ComponentVTable>, index: usize) -> Self {
|
||||||
Self { component, index }
|
Self { component, index }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a `Pin<ItemRef<'a>>`
|
/// Return a `Pin<ItemRef<'a>>`
|
||||||
pub fn borrow<'a>(&'a self) -> Pin<ItemRef<'a>> {
|
pub fn borrow<'a>(&'a self) -> Pin<ItemRef<'a>> {
|
||||||
let comp_ref_pin = vtable::VRc::borrow_pin(&self.component);
|
let comp_ref_pin = vtable::VRc::borrow_pin(&self.component);
|
||||||
|
|
@ -185,15 +188,29 @@ impl ItemRc {
|
||||||
// lifetime of the component, which is 'a. Pin::as_ref removes the lifetime, but we can just put it back.
|
// lifetime of the component, which is 'a. Pin::as_ref removes the lifetime, but we can just put it back.
|
||||||
unsafe { core::mem::transmute::<Pin<ItemRef<'_>>, Pin<ItemRef<'a>>>(result) }
|
unsafe { core::mem::transmute::<Pin<ItemRef<'_>>, Pin<ItemRef<'a>>>(result) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downgrade(&self) -> ItemWeak {
|
pub fn downgrade(&self) -> ItemWeak {
|
||||||
ItemWeak { component: VRc::downgrade(&self.component), index: self.index }
|
ItemWeak { component: VRc::downgrade(&self.component), index: self.index }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the parent Item in the item tree.
|
/// Return the parent Item in the item tree.
|
||||||
/// This is weak because it can be null if there is no parent
|
/// This is weak because it can be null if there is no parent
|
||||||
pub fn parent_item(&self) -> ItemWeak {
|
pub fn parent_item(&self) -> ItemWeak {
|
||||||
let comp_ref_pin = vtable::VRc::borrow_pin(&self.component);
|
let comp_ref_pin = vtable::VRc::borrow_pin(&self.component);
|
||||||
|
let item_tree = crate::item_tree::ComponentItemTree::new(
|
||||||
|
comp_ref_pin.as_ref().get_item_tree().as_slice(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(parent_index) = item_tree.parent(self.index) {
|
||||||
|
return ItemRc::new(self.component.clone(), parent_index).downgrade();
|
||||||
|
}
|
||||||
|
|
||||||
let mut r = ItemWeak::default();
|
let mut r = ItemWeak::default();
|
||||||
comp_ref_pin.as_ref().parent_item(self.index, &mut r);
|
comp_ref_pin.as_ref().parent_item(self.index, &mut r);
|
||||||
|
// parent_item returns the repeater node, go up one more level!
|
||||||
|
if let Some(rc) = r.upgrade() {
|
||||||
|
r = rc.parent_item();
|
||||||
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore vecmodel
|
||||||
|
|
||||||
//! Model and Repeater
|
//! Model and Repeater
|
||||||
|
|
||||||
// Safety: we use pointer to Repeater in the DependencyList, bue the Drop of the Repeater
|
// Safety: we use pointer to Repeater in the DependencyList, bue the Drop of the Repeater
|
||||||
// will remove them from the list so it will not be accessed after it is dropped
|
// will remove them from the list so it will not be accessed after it is dropped
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
|
use crate::component::ComponentVTable;
|
||||||
use crate::item_tree::TraversalOrder;
|
use crate::item_tree::TraversalOrder;
|
||||||
use crate::items::ItemRef;
|
use crate::items::ItemRef;
|
||||||
use crate::layout::Orientation;
|
use crate::layout::Orientation;
|
||||||
|
|
@ -567,7 +570,9 @@ impl<T> Model for ModelRc<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Component that can be instantiated by a repeater.
|
/// Component that can be instantiated by a repeater.
|
||||||
pub trait RepeatedComponent: crate::component::Component {
|
pub trait RepeatedComponent:
|
||||||
|
crate::component::Component + vtable::HasStaticVTable<ComponentVTable> + 'static
|
||||||
|
{
|
||||||
/// The data corresponding to the model
|
/// The data corresponding to the model
|
||||||
type Data: 'static;
|
type Data: 'static;
|
||||||
|
|
||||||
|
|
@ -615,6 +620,7 @@ impl<C: RepeatedComponent> Default for RepeaterInner<C> {
|
||||||
RepeaterInner { components: Default::default(), offset: 0, cached_item_height: 0. }
|
RepeaterInner { components: Default::default(), offset: 0, cached_item_height: 0. }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ErasedRepeater {
|
trait ErasedRepeater {
|
||||||
fn row_changed(&self, row: usize);
|
fn row_changed(&self, row: usize);
|
||||||
fn row_added(&self, index: usize, count: usize);
|
fn row_added(&self, index: usize, count: usize);
|
||||||
|
|
@ -968,7 +974,24 @@ impl<C: RepeatedComponent> Repeater<C> {
|
||||||
self.inner.borrow().components.len()
|
self.inner.borrow().components.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the Repeater is empty
|
/// Return the range of indices used by this Repeater.
|
||||||
|
///
|
||||||
|
/// Two values are necessary here since the Repeater can start to insert the data from its
|
||||||
|
/// model at an offset.
|
||||||
|
pub fn range(&self) -> (usize, usize) {
|
||||||
|
let inner = self.inner.borrow();
|
||||||
|
(inner.offset, inner.offset + inner.components.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component_at(&self, index: usize) -> Option<ComponentRc<C>> {
|
||||||
|
self.inner
|
||||||
|
.borrow()
|
||||||
|
.components
|
||||||
|
.get(index)
|
||||||
|
.map(|c| c.1.clone().expect("That was updated before!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return true if the Repeater as empty
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||||
|
|
||||||
|
// cSpell: ignore dealloc refcell unerase
|
||||||
|
|
||||||
use crate::{api::Value, dynamic_type, eval};
|
use crate::{api::Value, dynamic_type, eval};
|
||||||
|
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
@ -12,7 +14,9 @@ use i_slint_compiler::object_tree::ElementRc;
|
||||||
use i_slint_compiler::*;
|
use i_slint_compiler::*;
|
||||||
use i_slint_compiler::{diagnostics::BuildDiagnostics, object_tree::PropertyDeclaration};
|
use i_slint_compiler::{diagnostics::BuildDiagnostics, object_tree::PropertyDeclaration};
|
||||||
use i_slint_core::api::Window;
|
use i_slint_core::api::Window;
|
||||||
use i_slint_core::component::{Component, ComponentRef, ComponentRefPin, ComponentVTable};
|
use i_slint_core::component::{
|
||||||
|
Component, ComponentRef, ComponentRefPin, ComponentVTable, ComponentWeak, IndexRange,
|
||||||
|
};
|
||||||
use i_slint_core::item_tree::{
|
use i_slint_core::item_tree::{
|
||||||
ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult,
|
ItemTreeNode, ItemVisitorRefMut, ItemVisitorVTable, TraversalOrder, VisitChildrenResult,
|
||||||
};
|
};
|
||||||
|
|
@ -174,9 +178,26 @@ impl Component for ErasedComponentBox {
|
||||||
unsafe { get_item_ref(self.get_ref().borrow(), index) }
|
unsafe { get_item_ref(self.get_ref().borrow(), index) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_subtree_range(self: Pin<&Self>, index: usize) -> IndexRange {
|
||||||
|
self.borrow().as_ref().get_subtree_range(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_subtree_component(
|
||||||
|
self: Pin<&Self>,
|
||||||
|
index: usize,
|
||||||
|
subindex: usize,
|
||||||
|
result: &mut ComponentWeak,
|
||||||
|
) {
|
||||||
|
self.borrow().as_ref().get_subtree_component(index, subindex, result);
|
||||||
|
}
|
||||||
|
|
||||||
fn parent_item(self: Pin<&Self>, index: usize, result: &mut ItemWeak) {
|
fn parent_item(self: Pin<&Self>, index: usize, result: &mut ItemWeak) {
|
||||||
self.borrow().as_ref().parent_item(index, result)
|
self.borrow().as_ref().parent_item(index, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn subtree_index(self: Pin<&Self>) -> usize {
|
||||||
|
self.borrow().as_ref().subtree_index()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i_slint_core::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComponentBox);
|
i_slint_core::ComponentVTable_static!(static COMPONENT_BOX_VT for ErasedComponentBox);
|
||||||
|
|
@ -1030,7 +1051,10 @@ pub(crate) fn generate_component<'id>(
|
||||||
layout_info,
|
layout_info,
|
||||||
get_item_ref,
|
get_item_ref,
|
||||||
get_item_tree,
|
get_item_tree,
|
||||||
|
get_subtree_range,
|
||||||
|
get_subtree_component,
|
||||||
parent_item,
|
parent_item,
|
||||||
|
subtree_index,
|
||||||
drop_in_place,
|
drop_in_place,
|
||||||
dealloc,
|
dealloc,
|
||||||
};
|
};
|
||||||
|
|
@ -1518,6 +1542,34 @@ unsafe extern "C" fn get_item_ref(component: ComponentRefPin, index: usize) -> P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn get_subtree_range(component: ComponentRefPin, index: usize) -> IndexRange {
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
let rep_in_comp = unsafe { instance_ref.component_type.repeater[index].get_untagged() };
|
||||||
|
ensure_repeater_updated(instance_ref, rep_in_comp);
|
||||||
|
|
||||||
|
let repeater = rep_in_comp.offset.apply(&instance_ref.instance);
|
||||||
|
let (start, end) = repeater.range();
|
||||||
|
IndexRange { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn get_subtree_component(
|
||||||
|
component: ComponentRefPin,
|
||||||
|
index: usize,
|
||||||
|
subtree_index: usize,
|
||||||
|
result: &mut ComponentWeak,
|
||||||
|
) {
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
let rep_in_comp = unsafe { instance_ref.component_type.repeater[index].get_untagged() };
|
||||||
|
ensure_repeater_updated(instance_ref, rep_in_comp);
|
||||||
|
|
||||||
|
let repeater = rep_in_comp.offset.apply(&instance_ref.instance);
|
||||||
|
*result = vtable::VRc::downgrade(&vtable::VRc::into_dyn(
|
||||||
|
repeater.component_at(subtree_index).unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" fn get_item_tree(component: ComponentRefPin) -> Slice<ItemTreeNode> {
|
extern "C" fn get_item_tree(component: ComponentRefPin) -> Slice<ItemTreeNode> {
|
||||||
generativity::make_guard!(guard);
|
generativity::make_guard!(guard);
|
||||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
|
@ -1525,6 +1577,16 @@ extern "C" fn get_item_tree(component: ComponentRefPin) -> Slice<ItemTreeNode> {
|
||||||
unsafe { core::mem::transmute::<&[ItemTreeNode], &[ItemTreeNode]>(tree) }.into()
|
unsafe { core::mem::transmute::<&[ItemTreeNode], &[ItemTreeNode]>(tree) }.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn subtree_index(component: ComponentRefPin) -> usize {
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
if let Ok(value) = instance_ref.component_type.get_property(component, "index") {
|
||||||
|
value.try_into().unwrap()
|
||||||
|
} else {
|
||||||
|
core::usize::MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize, result: &mut ItemWeak) {
|
unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize, result: &mut ItemWeak) {
|
||||||
generativity::make_guard!(guard);
|
generativity::make_guard!(guard);
|
||||||
let instance_ref = InstanceRef::from_pin_ref(component, guard);
|
let instance_ref = InstanceRef::from_pin_ref(component, guard);
|
||||||
|
|
@ -1549,7 +1611,7 @@ unsafe extern "C" fn parent_item(component: ComponentRefPin, index: usize, resul
|
||||||
.into_dyn()
|
.into_dyn()
|
||||||
.upgrade()
|
.upgrade()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
*result = ItemRc::new(parent_rc, parent_index).parent_item();
|
*result = ItemRc::new(parent_rc, parent_index).downgrade();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue