i_slint_core/
component_factory.rs1#![warn(missing_docs)]
5
6use crate::api::ComponentHandle;
8use crate::item_tree::{ItemTreeRc, ItemTreeVTable, ItemTreeWeak};
9use alloc::boxed::Box;
10use alloc::rc::Rc;
11use core::fmt::Debug;
12
13pub struct FactoryContext {
15 pub parent_item_tree: ItemTreeWeak,
17 pub parent_item_tree_index: u32,
20}
21
22#[derive(Clone)]
23struct ComponentFactoryInner(Rc<dyn Fn(FactoryContext) -> Option<ItemTreeRc> + 'static>);
24
25impl PartialEq for ComponentFactoryInner {
26 fn eq(&self, other: &Self) -> bool {
27 Rc::ptr_eq(&self.0, &other.0)
28 }
29}
30
31impl Debug for ComponentFactoryInner {
32 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
33 f.debug_tuple("ComponentFactoryData").finish()
34 }
35}
36
37#[derive(Clone, Debug, Default, PartialEq)]
49pub struct ComponentFactory(Option<ComponentFactoryInner>);
50
51impl ComponentFactory {
52 pub fn new<
54 X: vtable::HasStaticVTable<ItemTreeVTable> + 'static,
55 T: ComponentHandle<WeakInner = vtable::VWeak<ItemTreeVTable, X>> + 'static,
56 >(
57 factory: impl Fn(FactoryContext) -> Option<T> + 'static,
58 ) -> Self {
59 let factory = Box::new(factory) as Box<dyn Fn(FactoryContext) -> Option<T> + 'static>;
60
61 Self(Some(ComponentFactoryInner(Rc::new(move |ctx| -> Option<ItemTreeRc> {
62 let product = (factory)(ctx);
63 product.map(|p| vtable::VRc::into_dyn(p.as_weak().inner().upgrade().unwrap()))
64 }))))
65 }
66
67 pub(crate) fn build(&self, ctx: FactoryContext) -> Option<ItemTreeRc> {
69 self.0.as_ref().and_then(move |b| (b.0)(ctx))
70 }
71}