#![warn(missing_docs)]
use crate::accessibility::AccessibleStringProperty;
use crate::item_tree::{
ItemTreeNode, ItemVisitorVTable, ItemWeak, TraversalOrder, VisitChildrenResult,
};
use crate::items::{AccessibleRole, ItemRc, ItemVTable};
use crate::layout::{LayoutInfo, Orientation};
use crate::slice::Slice;
use crate::window::WindowAdapterRc;
use crate::SharedString;
use vtable::*;
#[repr(C)]
pub struct IndexRange {
pub start: usize,
pub end: usize,
}
impl From<core::ops::Range<usize>> for IndexRange {
fn from(r: core::ops::Range<usize>) -> Self {
Self { start: r.start, end: r.end }
}
}
impl From<IndexRange> for core::ops::Range<usize> {
fn from(r: IndexRange) -> Self {
Self { start: r.start, end: r.end }
}
}
#[vtable]
#[repr(C)]
pub struct ComponentVTable {
pub visit_children_item: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
index: isize,
order: TraversalOrder,
visitor: VRefMut<ItemVisitorVTable>,
) -> VisitChildrenResult,
pub get_item_ref: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
index: usize,
) -> core::pin::Pin<VRef<ItemVTable>>,
pub get_subtree_range:
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, index: usize) -> IndexRange,
pub get_subtree_component: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
index: usize,
subindex: usize,
result: &mut vtable::VWeak<ComponentVTable, Dyn>,
),
pub get_item_tree: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> Slice<ItemTreeNode>,
pub parent_node: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, result: &mut ItemWeak),
pub embed_component: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
parent_component: &VWeak<ComponentVTable>,
parent_item_tree_index: usize,
) -> bool,
pub subtree_index: extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>) -> usize,
pub layout_info:
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, Orientation) -> LayoutInfo,
pub accessible_role:
extern "C" fn(core::pin::Pin<VRef<ComponentVTable>>, item_index: usize) -> AccessibleRole,
pub accessible_string_property: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
item_index: usize,
what: AccessibleStringProperty,
result: &mut SharedString,
),
pub window_adapter: extern "C" fn(
core::pin::Pin<VRef<ComponentVTable>>,
do_create: bool,
result: &mut Option<WindowAdapterRc>,
),
pub drop_in_place: unsafe fn(VRefMut<ComponentVTable>) -> vtable::Layout,
pub dealloc: unsafe fn(&ComponentVTable, ptr: *mut u8, layout: vtable::Layout),
}
#[cfg(test)]
pub(crate) use ComponentVTable_static;
pub type ComponentRef<'a> = vtable::VRef<'a, ComponentVTable>;
pub type ComponentRefPin<'a> = core::pin::Pin<ComponentRef<'a>>;
pub type ComponentRc = vtable::VRc<ComponentVTable, Dyn>;
pub type ComponentWeak = vtable::VWeak<ComponentVTable, Dyn>;
pub fn register_component(component_rc: &ComponentRc, window_adapter: Option<WindowAdapterRc>) {
let c = vtable::VRc::borrow_pin(component_rc);
let item_tree = c.as_ref().get_item_tree();
item_tree.iter().enumerate().for_each(|(tree_index, node)| {
if let ItemTreeNode::Item { .. } = &node {
let item = ItemRc::new(component_rc.clone(), tree_index);
c.as_ref().get_item_ref(tree_index).as_ref().init(&item);
}
});
if let Some(adapter) = window_adapter.as_ref().and_then(|a| a.internal(crate::InternalToken)) {
adapter.register_component();
}
}
pub fn unregister_component<Base>(
base: core::pin::Pin<&Base>,
component: ComponentRef,
item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
window_adapter: &WindowAdapterRc,
) {
window_adapter.renderer().free_graphics_resources(
component,
&mut item_array.iter().map(|item| item.apply_pin(base)),
).expect("Fatal error encountered when freeing graphics resources while destroying Slint component");
if let Some(w) = window_adapter.internal(crate::InternalToken) {
w.unregister_component(component, &mut item_array.iter().map(|item| item.apply_pin(base)));
}
}
#[cfg(feature = "ffi")]
pub(crate) mod ffi {
#![allow(unsafe_code)]
use crate::window::WindowAdapterRc;
use super::*;
#[no_mangle]
pub unsafe extern "C" fn slint_register_component(
component_rc: &ComponentRc,
window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
) {
let window_adapter = (window_handle as *const WindowAdapterRc).as_ref().cloned();
super::register_component(component_rc, window_adapter)
}
#[no_mangle]
pub unsafe extern "C" fn slint_unregister_component(
component: ComponentRefPin,
item_array: Slice<vtable::VOffset<u8, ItemVTable, vtable::AllowPin>>,
window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
) {
let window_adapter = &*(window_handle as *const WindowAdapterRc);
super::unregister_component(
core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
core::pin::Pin::into_inner(component),
item_array.as_slice(),
window_adapter,
)
}
}