| 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 | |