Program Listing for File slint.h¶
↰ Return to documentation for file (/home/runner/work/slint/slint/api/cpp/include/slint.h)
// Copyright © SixtyFPS GmbH <[email protected]>
// 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_platform_internal.h"
#include "slint_qt_internal.h"
#include "slint_window.h"
#include "slint_models.h"
#include "slint_item_tree.h"
#include <vector>
#include <chrono>
#include <span>
#include <concepts>
#ifndef SLINT_FEATURE_FREESTANDING
# include <mutex>
# include <condition_variable>
#endif
namespace slint {
namespace private_api {
inline cbindgen_private::Rect convert_anonymous_rect(std::tuple<float, float, float, float> tuple)
{
// alphabetical order
auto [h, w, x, y] = tuple;
return cbindgen_private::Rect { .x = x, .y = y, .width = w, .height = h };
}
inline void dealloc(const ItemTreeVTable *vtable, uint8_t *ptr,
[[maybe_unused]] vtable::Layout layout)
{
vtable::dealloc(vtable, ptr, layout);
}
template<typename T>
inline vtable::Layout drop_in_place(ItemTreeRef item_tree)
{
return vtable::drop_in_place<ItemTreeVTable, T>(item_tree);
}
#if !defined(DOXYGEN)
# if defined(_WIN32) || defined(_WIN64)
// On Windows cross-dll data relocations are not supported:
// https://docs.microsoft.com/en-us/cpp/c-language/rules-and-limitations-for-dllimport-dllexport?view=msvc-160
// so we have a relocation to a function that returns the address we seek. That
// relocation will be resolved to the locally linked stub library, the implementation of
// which will be patched.
# define SLINT_GET_ITEM_VTABLE(VTableName) slint::private_api::slint_get_##VTableName()
# else
# define SLINT_GET_ITEM_VTABLE(VTableName) (&slint::private_api::VTableName)
# endif
#endif // !defined(DOXYGEN)
inline std::optional<cbindgen_private::ItemRc>
upgrade_item_weak(const cbindgen_private::ItemWeak &item_weak)
{
if (auto item_tree_strong = item_weak.item_tree.lock()) {
return { { *item_tree_strong, item_weak.index } };
} else {
return std::nullopt;
}
}
inline void debug(const SharedString &str)
{
cbindgen_private::slint_debug(&str);
}
} // namespace private_api
namespace cbindgen_private {
inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const
{
// Note: This "logic" is duplicated from LayoutInfo::merge in layout.rs.
return LayoutInfo { std::min(max, other.max),
std::min(max_percent, other.max_percent),
std::max(min, other.min),
std::max(min_percent, other.min_percent),
std::max(preferred, other.preferred),
std::min(stretch, other.stretch) };
}
inline bool operator==(const EasingCurve &a, const EasingCurve &b)
{
if (a.tag != b.tag) {
return false;
} else if (a.tag == EasingCurve::Tag::CubicBezier) {
return std::equal(a.cubic_bezier._0, a.cubic_bezier._0 + 4, b.cubic_bezier._0);
}
return true;
}
}
namespace private_api {
inline static void register_item_tree(const vtable::VRc<ItemTreeVTable> *c,
const std::optional<slint::Window> &maybe_window)
{
const cbindgen_private::WindowAdapterRcOpaque *window_ptr =
maybe_window.has_value() ? &maybe_window->window_handle().handle() : nullptr;
cbindgen_private::slint_register_item_tree(c, window_ptr);
}
inline SharedVector<float> solve_box_layout(const cbindgen_private::BoxLayoutData &data,
cbindgen_private::Slice<int> repeater_indexes)
{
SharedVector<float> result;
cbindgen_private::Slice<uint32_t> ri =
make_slice(reinterpret_cast<uint32_t *>(repeater_indexes.ptr), repeater_indexes.len);
cbindgen_private::slint_solve_box_layout(&data, ri, &result);
return result;
}
inline SharedVector<float> solve_grid_layout(const cbindgen_private::GridLayoutData &data)
{
SharedVector<float> result;
cbindgen_private::slint_solve_grid_layout(&data, &result);
return result;
}
inline cbindgen_private::LayoutInfo
grid_layout_info(cbindgen_private::Slice<cbindgen_private::GridLayoutCellData> cells, float spacing,
const cbindgen_private::Padding &padding)
{
return cbindgen_private::slint_grid_layout_info(cells, spacing, &padding);
}
inline cbindgen_private::LayoutInfo
box_layout_info(cbindgen_private::Slice<cbindgen_private::BoxLayoutCellData> cells, float spacing,
const cbindgen_private::Padding &padding,
cbindgen_private::LayoutAlignment alignment)
{
return cbindgen_private::slint_box_layout_info(cells, spacing, &padding, alignment);
}
inline cbindgen_private::LayoutInfo
box_layout_info_ortho(cbindgen_private::Slice<cbindgen_private::BoxLayoutCellData> cells,
const cbindgen_private::Padding &padding)
{
return cbindgen_private::slint_box_layout_info_ortho(cells, &padding);
}
inline float layout_cache_access(const SharedVector<float> &cache, int offset, int repeater_index)
{
size_t idx = size_t(cache[offset]) + repeater_index * 2;
return idx < cache.size() ? cache[idx] : 0;
}
template<typename VT, typename ItemType>
inline cbindgen_private::LayoutInfo
item_layout_info(VT *itemvtable, ItemType *item_ptr, cbindgen_private::Orientation orientation,
WindowAdapterRc *window_adapter, const ItemTreeRc &component_rc,
uint32_t item_index)
{
cbindgen_private::ItemRc item_rc { component_rc, item_index };
return itemvtable->layout_info({ itemvtable, item_ptr }, orientation, window_adapter, &item_rc);
}
} // namespace private_api
namespace private_api {
template<typename T>
union MaybeUninitialized {
T value;
~MaybeUninitialized() { }
MaybeUninitialized() { }
T take()
{
T result = std::move(value);
value.~T();
return result;
}
};
inline vtable::VRc<cbindgen_private::MenuVTable>
create_menu_wrapper(const ItemTreeRc &menu_item_tree,
bool (*condition)(const ItemTreeRc *menu_tree) = nullptr)
{
MaybeUninitialized<vtable::VRc<cbindgen_private::MenuVTable>> maybe;
cbindgen_private::slint_menus_create_wrapper(&menu_item_tree, &maybe.value, condition);
return maybe.take();
}
inline void setup_popup_menu_from_menu_item_tree(
const vtable::VRc<cbindgen_private::MenuVTable> &shared,
Property<std::shared_ptr<Model<cbindgen_private::MenuEntry>>> &entries,
Callback<std::shared_ptr<Model<cbindgen_private::MenuEntry>>(cbindgen_private::MenuEntry)>
&sub_menu,
Callback<void(cbindgen_private::MenuEntry)> &activated)
{
using cbindgen_private::MenuEntry;
entries.set_binding([shared] {
SharedVector<MenuEntry> entries_sv;
shared.vtable()->sub_menu(shared.borrow(), nullptr, &entries_sv);
std::vector<MenuEntry> entries_vec(entries_sv.begin(), entries_sv.end());
return std::make_shared<VectorModel<MenuEntry>>(std::move(entries_vec));
});
sub_menu.set_handler([shared](const auto &entry) {
SharedVector<MenuEntry> entries_sv;
shared.vtable()->sub_menu(shared.borrow(), &entry, &entries_sv);
std::vector<MenuEntry> entries_vec(entries_sv.begin(), entries_sv.end());
return std::make_shared<VectorModel<MenuEntry>>(std::move(entries_vec));
});
activated.set_handler(
[shared](const auto &entry) { shared.vtable()->activate(shared.borrow(), &entry); });
}
inline SharedString translate(const SharedString &original, const SharedString &context,
const SharedString &domain,
cbindgen_private::Slice<SharedString> arguments, int n,
const SharedString &plural)
{
SharedString result = original;
cbindgen_private::slint_translate(&result, &context, &domain, arguments, n, &plural);
return result;
}
inline SharedString translate_from_bundle(std::span<const char8_t *const> strs,
cbindgen_private::Slice<SharedString> arguments)
{
SharedString result;
cbindgen_private::slint_translate_from_bundle(
make_slice((reinterpret_cast<char const *const *>(strs.data())), strs.size()),
arguments, &result);
return result;
}
inline SharedString
translate_from_bundle_with_plural(std::span<const char8_t *const> strs,
std::span<const uint32_t> indices,
std::span<uintptr_t (*const)(int32_t)> plural_rules,
cbindgen_private::Slice<SharedString> arguments, int n)
{
SharedString result;
cbindgen_private::Slice<const char *> strs_slice =
make_slice(reinterpret_cast<char const *const *>(strs.data()), strs.size());
cbindgen_private::Slice<uint32_t> indices_slice =
make_slice(reinterpret_cast<const uint32_t *>(indices.data()), indices.size());
cbindgen_private::Slice<uintptr_t (*)(int32_t)> plural_rules_slice =
make_slice(reinterpret_cast<uintptr_t (*const *)(int32_t)>(plural_rules.data()),
plural_rules.size());
cbindgen_private::slint_translate_from_bundle_with_plural(
strs_slice, indices_slice, plural_rules_slice, arguments, n, &result);
return result;
}
template<typename Component>
inline float get_resolved_default_font_size(const Component &component)
{
ItemTreeRc item_tree_rc = (*component.self_weak.lock()).into_dyn();
return slint::cbindgen_private::slint_windowrc_resolved_default_font_size(&item_tree_rc);
}
} // namespace private_api
#ifdef SLINT_FEATURE_GETTEXT
inline void update_all_translations()
{
cbindgen_private::slint_translations_mark_dirty();
}
#endif
inline bool select_bundled_translation(std::string_view language)
{
return cbindgen_private::slint_translate_select_bundled_translation(
slint::private_api::string_to_slice(language));
}
#if !defined(DOXYGEN)
cbindgen_private::Flickable::Flickable()
{
slint_flickable_data_init(&data);
}
cbindgen_private::Flickable::~Flickable()
{
slint_flickable_data_free(&data);
}
cbindgen_private::NativeStyleMetrics::NativeStyleMetrics(void *)
{
slint_native_style_metrics_init(this);
}
cbindgen_private::NativeStyleMetrics::~NativeStyleMetrics()
{
slint_native_style_metrics_deinit(this);
}
cbindgen_private::NativePalette::NativePalette(void *)
{
slint_native_palette_init(this);
}
cbindgen_private::NativePalette::~NativePalette()
{
slint_native_palette_deinit(this);
}
#endif // !defined(DOXYGEN)
namespace private_api {
// Was used in Slint <= 1.1.0 to have an error message in case of mismatch
template<int Major, int Minor, int Patch>
struct [[deprecated]] VersionCheckHelper
{
};
}
enum class EventLoopMode {
QuitOnLastWindowClosed,
RunUntilQuit
};
inline void run_event_loop(EventLoopMode mode = EventLoopMode::QuitOnLastWindowClosed)
{
private_api::assert_main_thread();
cbindgen_private::slint_run_event_loop(mode == EventLoopMode::QuitOnLastWindowClosed);
}
inline void quit_event_loop()
{
cbindgen_private::slint_quit_event_loop();
}
template<std::invocable Functor>
void invoke_from_event_loop(Functor f)
{
cbindgen_private::slint_post_event(
[](void *data) { (*reinterpret_cast<Functor *>(data))(); }, new Functor(std::move(f)),
[](void *data) { delete reinterpret_cast<Functor *>(data); });
}
#if !defined(SLINT_FEATURE_FREESTANDING) || defined(DOXYGEN)
template<std::invocable Functor>
auto blocking_invoke_from_event_loop(Functor f) -> std::invoke_result_t<Functor>
{
std::optional<std::invoke_result_t<Functor>> result;
std::mutex mtx;
std::condition_variable cv;
invoke_from_event_loop([&] {
auto r = f();
std::unique_lock lock(mtx);
result = std::move(r);
cv.notify_one();
});
std::unique_lock lock(mtx);
cv.wait(lock, [&] { return result.has_value(); });
return std::move(*result);
}
# if !defined(DOXYGEN) // Doxygen doesn't see this as an overload of the previous one
// clang-format off
template<std::invocable Functor>
requires(std::is_void_v<std::invoke_result_t<Functor>>)
void blocking_invoke_from_event_loop(Functor f)
// clang-format on
{
std::mutex mtx;
std::condition_variable cv;
bool ok = false;
invoke_from_event_loop([&] {
f();
std::unique_lock lock(mtx);
ok = true;
cv.notify_one();
});
std::unique_lock lock(mtx);
cv.wait(lock, [&] { return ok; });
}
# endif
#endif
inline void set_xdg_app_id(std::string_view xdg_app_id)
{
private_api::assert_main_thread();
SharedString s = xdg_app_id;
cbindgen_private::slint_set_xdg_app_id(&s);
}
} // namespace slint