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 | #pragma once |
5 | |
6 | #include "slint_internal.h" |
7 | #include "slint_window.h" |
8 | |
9 | namespace slint { |
10 | namespace private_api { |
11 | // Bring opaque structure in scope |
12 | using namespace cbindgen_private; |
13 | using ItemTreeRef = vtable::VRef<private_api::ItemTreeVTable>; |
14 | using IndexRange = cbindgen_private::IndexRange; |
15 | using ItemRef = vtable::VRef<private_api::ItemVTable>; |
16 | using ItemVisitorRefMut = vtable::VRefMut<cbindgen_private::ItemVisitorVTable>; |
17 | using ItemTreeNode = cbindgen_private::ItemTreeNode; |
18 | using ItemArrayEntry = |
19 | vtable::VOffset<uint8_t, slint::cbindgen_private::ItemVTable, vtable::AllowPin>; |
20 | using ItemArray = slint::cbindgen_private::Slice<ItemArrayEntry>; |
21 | |
22 | constexpr inline ItemTreeNode make_item_node(uint32_t child_count, uint32_t child_index, |
23 | uint32_t parent_index, uint32_t item_array_index, |
24 | bool is_accessible) |
25 | { |
26 | return ItemTreeNode { ItemTreeNode::Item_Body { .tag: ItemTreeNode::Tag::Item, .is_accessible: is_accessible, |
27 | .children_count: child_count, .children_index: child_index, .parent_index: parent_index, |
28 | .item_array_index: item_array_index } }; |
29 | } |
30 | |
31 | constexpr inline ItemTreeNode make_dyn_node(std::uint32_t offset, std::uint32_t parent_index) |
32 | { |
33 | return ItemTreeNode { ItemTreeNode::DynamicTree_Body { .tag: ItemTreeNode::Tag::DynamicTree, .index: offset, |
34 | .parent_index: parent_index } }; |
35 | } |
36 | |
37 | inline ItemRef get_item_ref(ItemTreeRef item_tree, |
38 | const cbindgen_private::Slice<ItemTreeNode> item_tree_array, |
39 | const private_api::ItemArray item_array, int index) |
40 | { |
41 | const auto item_array_index = item_tree_array.ptr[index].item.item_array_index; |
42 | const auto item = item_array[item_array_index]; |
43 | return ItemRef { .vtable: item.vtable, .instance: reinterpret_cast<char *>(item_tree.instance) + item.offset }; |
44 | } |
45 | |
46 | } // namespace private_api |
47 | |
48 | template<typename T> |
49 | class ComponentWeakHandle; |
50 | |
51 | /// The component handle is like a shared pointer to a component in the generated code. |
52 | /// In order to get a component, use `T::create()` where T is the name of the component |
53 | /// in the .slint file. This give you a `ComponentHandle<T>` |
54 | template<typename T> |
55 | class ComponentHandle |
56 | { |
57 | vtable::VRc<private_api::ItemTreeVTable, T> inner; |
58 | friend class ComponentWeakHandle<T>; |
59 | |
60 | public: |
61 | /// internal constructor |
62 | ComponentHandle(const vtable::VRc<private_api::ItemTreeVTable, T> &inner) : inner(inner) { } |
63 | |
64 | /// Arrow operator that implements pointer semantics. |
65 | const T *operator->() const |
66 | { |
67 | private_api::assert_main_thread(); |
68 | return inner.operator->(); |
69 | } |
70 | /// Dereference operator that implements pointer semantics. |
71 | const T &operator*() const |
72 | { |
73 | private_api::assert_main_thread(); |
74 | return inner.operator*(); |
75 | } |
76 | /// Arrow operator that implements pointer semantics. |
77 | T *operator->() |
78 | { |
79 | private_api::assert_main_thread(); |
80 | return inner.operator->(); |
81 | } |
82 | /// Dereference operator that implements pointer semantics. |
83 | T &operator*() |
84 | { |
85 | private_api::assert_main_thread(); |
86 | return inner.operator*(); |
87 | } |
88 | |
89 | /// internal function that returns the internal handle |
90 | vtable::VRc<private_api::ItemTreeVTable> into_dyn() const { return inner.into_dyn(); } |
91 | }; |
92 | |
93 | /// A weak reference to the component. Can be constructed from a `ComponentHandle<T>` |
94 | template<typename T> |
95 | class ComponentWeakHandle |
96 | { |
97 | vtable::VWeak<private_api::ItemTreeVTable, T> inner; |
98 | |
99 | public: |
100 | /// Constructs a null ComponentWeakHandle. lock() will always return empty. |
101 | ComponentWeakHandle() = default; |
102 | /// Copy-constructs a new ComponentWeakHandle from \a other. |
103 | ComponentWeakHandle(const ComponentHandle<T> &other) : inner(other.inner) { } |
104 | /// Returns a new strong ComponentHandle<T> if the component the weak handle points to is |
105 | /// still referenced by any other ComponentHandle<T>. An empty std::optional is returned |
106 | /// otherwise. |
107 | std::optional<ComponentHandle<T>> lock() const |
108 | { |
109 | private_api::assert_main_thread(); |
110 | if (auto l = inner.lock()) { |
111 | return { ComponentHandle(*l) }; |
112 | } else { |
113 | return {}; |
114 | } |
115 | } |
116 | }; |
117 | |
118 | } |
119 | |