Skip to main content

slint_interpreter/
item_registry.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4//! Maps a native item class name to a factory that allocates it.
5//!
6//! Built lazily on first access.
7//! Covers every builtin item in `i_slint_core::items` plus the backend-specific
8//! widgets exposed through `i_slint_backend_selector::NativeWidgets`.
9
10use crate::erased::ErasedItemRc;
11use crate::item_holder::make_item;
12use i_slint_core::items::*;
13use i_slint_core::rtti::BuiltinItem;
14use std::collections::HashMap;
15use std::sync::OnceLock;
16
17pub type ItemFactory = fn() -> ErasedItemRc;
18
19pub struct ItemRegistry {
20    factories: HashMap<&'static str, ItemFactory>,
21}
22
23impl ItemRegistry {
24    pub fn factory(&self, class_name: &str) -> Option<ItemFactory> {
25        self.factories.get(class_name).copied()
26    }
27
28    pub fn global() -> &'static ItemRegistry {
29        static REGISTRY: OnceLock<ItemRegistry> = OnceLock::new();
30        REGISTRY.get_or_init(ItemRegistry::build)
31    }
32
33    fn build() -> Self {
34        let mut factories: HashMap<&'static str, ItemFactory> = HashMap::new();
35
36        macro_rules! reg {
37            ($($ty:ident),* $(,)?) => {
38                $(
39                    factories.insert(<$ty as BuiltinItem>::name(), make_item::<$ty> as ItemFactory);
40                )*
41            };
42        }
43
44        reg!(
45            ComponentContainer,
46            Empty,
47            ImageItem,
48            ClippedImage,
49            ComplexText,
50            StyledTextItem,
51            SimpleText,
52            Rectangle,
53            BasicBorderRectangle,
54            BorderRectangle,
55            TouchArea,
56            TooltipArea,
57            FocusScope,
58            KeyBinding,
59            SwipeGestureHandler,
60            ScaleRotateGestureHandler,
61            Path,
62            Flickable,
63            WindowItem,
64            TextInput,
65            Clip,
66            BoxShadow,
67            Transform,
68            Opacity,
69            Layer,
70            DragArea,
71            DropArea,
72            WindowMoveArea,
73            ContextMenu,
74            MenuItem,
75            SystemTrayIcon,
76        );
77
78        // Walk the backend's `NativeWidgets` type list and register each entry.
79        <i_slint_backend_selector::NativeWidgets as NativeHelper>::push(&mut factories);
80
81        ItemRegistry { factories }
82    }
83}
84
85/// Walks a nested-tuple type list `(T1, (T2, (…, ())))` and registers each `Ti`.
86trait NativeHelper {
87    fn push(factories: &mut HashMap<&'static str, ItemFactory>);
88}
89
90impl NativeHelper for () {
91    fn push(_: &mut HashMap<&'static str, ItemFactory>) {}
92}
93
94impl<T: 'static + Default + BuiltinItem + vtable::HasStaticVTable<ItemVTable>, Next: NativeHelper>
95    NativeHelper for (T, Next)
96{
97    fn push(factories: &mut HashMap<&'static str, ItemFactory>) {
98        factories.insert(<T as BuiltinItem>::name(), make_item::<T> as ItemFactory);
99        Next::push(factories);
100    }
101}