mirror of
https://github.com/slint-ui/slint.git
synced 2025-07-15 17:15:27 +00:00

Most of the slint.h file is used for model code, so before doing some work on the model i wanted to refactor the code in its own file. Since the model need access to the ComponentHandle, i also had to move that in its own file
118 lines
4.3 KiB
C++
118 lines
4.3 KiB
C++
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
|
|
|
#pragma once
|
|
|
|
#include "slint_internal.h"
|
|
#include "slint_window.h"
|
|
|
|
namespace slint {
|
|
namespace private_api {
|
|
// Bring opaque structure in scope
|
|
using namespace cbindgen_private;
|
|
using ItemTreeRef = vtable::VRef<private_api::ItemTreeVTable>;
|
|
using IndexRange = cbindgen_private::IndexRange;
|
|
using ItemRef = vtable::VRef<private_api::ItemVTable>;
|
|
using ItemVisitorRefMut = vtable::VRefMut<cbindgen_private::ItemVisitorVTable>;
|
|
using ItemTreeNode = cbindgen_private::ItemTreeNode;
|
|
using ItemArrayEntry =
|
|
vtable::VOffset<uint8_t, slint::cbindgen_private::ItemVTable, vtable::AllowPin>;
|
|
using ItemArray = slint::cbindgen_private::Slice<ItemArrayEntry>;
|
|
|
|
constexpr inline ItemTreeNode make_item_node(uint32_t child_count, uint32_t child_index,
|
|
uint32_t parent_index, uint32_t item_array_index,
|
|
bool is_accessible)
|
|
{
|
|
return ItemTreeNode { ItemTreeNode::Item_Body { ItemTreeNode::Tag::Item, is_accessible,
|
|
child_count, child_index, parent_index,
|
|
item_array_index } };
|
|
}
|
|
|
|
constexpr inline ItemTreeNode make_dyn_node(std::uint32_t offset, std::uint32_t parent_index)
|
|
{
|
|
return ItemTreeNode { ItemTreeNode::DynamicTree_Body { ItemTreeNode::Tag::DynamicTree, offset,
|
|
parent_index } };
|
|
}
|
|
|
|
inline ItemRef get_item_ref(ItemTreeRef item_tree,
|
|
const cbindgen_private::Slice<ItemTreeNode> item_tree_array,
|
|
const private_api::ItemArray item_array, int index)
|
|
{
|
|
const auto item_array_index = item_tree_array.ptr[index].item.item_array_index;
|
|
const auto item = item_array[item_array_index];
|
|
return ItemRef { item.vtable, reinterpret_cast<char *>(item_tree.instance) + item.offset };
|
|
}
|
|
|
|
} // namespace private_api
|
|
|
|
template<typename T>
|
|
class ComponentWeakHandle;
|
|
|
|
/// The component handle is like a shared pointer to a component in the generated code.
|
|
/// In order to get a component, use `T::create()` where T is the name of the component
|
|
/// in the .slint file. This give you a `ComponentHandle<T>`
|
|
template<typename T>
|
|
class ComponentHandle
|
|
{
|
|
vtable::VRc<private_api::ItemTreeVTable, T> inner;
|
|
friend class ComponentWeakHandle<T>;
|
|
|
|
public:
|
|
/// internal constructor
|
|
ComponentHandle(const vtable::VRc<private_api::ItemTreeVTable, T> &inner) : inner(inner) { }
|
|
|
|
/// Arrow operator that implements pointer semantics.
|
|
const T *operator->() const
|
|
{
|
|
private_api::assert_main_thread();
|
|
return inner.operator->();
|
|
}
|
|
/// Dereference operator that implements pointer semantics.
|
|
const T &operator*() const
|
|
{
|
|
private_api::assert_main_thread();
|
|
return inner.operator*();
|
|
}
|
|
/// Arrow operator that implements pointer semantics.
|
|
T *operator->()
|
|
{
|
|
private_api::assert_main_thread();
|
|
return inner.operator->();
|
|
}
|
|
/// Dereference operator that implements pointer semantics.
|
|
T &operator*()
|
|
{
|
|
private_api::assert_main_thread();
|
|
return inner.operator*();
|
|
}
|
|
|
|
/// internal function that returns the internal handle
|
|
vtable::VRc<private_api::ItemTreeVTable> into_dyn() const { return inner.into_dyn(); }
|
|
};
|
|
|
|
/// A weak reference to the component. Can be constructed from a `ComponentHandle<T>`
|
|
template<typename T>
|
|
class ComponentWeakHandle
|
|
{
|
|
vtable::VWeak<private_api::ItemTreeVTable, T> inner;
|
|
|
|
public:
|
|
/// Constructs a null ComponentWeakHandle. lock() will always return empty.
|
|
ComponentWeakHandle() = default;
|
|
/// Copy-constructs a new ComponentWeakHandle from \a other.
|
|
ComponentWeakHandle(const ComponentHandle<T> &other) : inner(other.inner) { }
|
|
/// Returns a new strong ComponentHandle<T> if the component the weak handle points to is
|
|
/// still referenced by any other ComponentHandle<T>. An empty std::optional is returned
|
|
/// otherwise.
|
|
std::optional<ComponentHandle<T>> lock() const
|
|
{
|
|
private_api::assert_main_thread();
|
|
if (auto l = inner.lock()) {
|
|
return { ComponentHandle(*l) };
|
|
} else {
|
|
return {};
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|