mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 22:01:13 +00:00
ComponentDefinition::create in C++
Note thate there is a hack so `ComponentHandle<ComponentInstance>` (which is binary compatible with `VRc<ComponentVTable, ErasedComponentBox>` works
This commit is contained in:
parent
3ad41a551b
commit
f2ffc0ebf6
2 changed files with 85 additions and 19 deletions
|
@ -15,6 +15,15 @@ LICENSE END */
|
|||
|
||||
#include <optional>
|
||||
|
||||
namespace sixtyfps::cbindgen_private {
|
||||
// This has to stay opaque, but VRc don't compile if it is just forward declared
|
||||
struct ErasedComponentBox : vtable::Dyn {
|
||||
~ErasedComponentBox() = delete;
|
||||
ErasedComponentBox() = delete;
|
||||
ErasedComponentBox(ErasedComponentBox&) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
namespace sixtyfps::interpreter {
|
||||
|
||||
class Value;
|
||||
|
@ -349,21 +358,25 @@ inline void Struct::set_field(std::string_view name, const Value &value)
|
|||
cbindgen_private::sixtyfps_interpreter_struct_set_field(&inner, name_view, &value.inner);
|
||||
}
|
||||
|
||||
class ComponentInstance
|
||||
class ComponentInstance : vtable::Dyn
|
||||
{
|
||||
cbindgen_private::ComponentInstance inner;
|
||||
ComponentInstance() = delete;
|
||||
ComponentInstance(ComponentInstance &) = delete;
|
||||
ComponentInstance &operator=(ComponentInstance &) = delete;
|
||||
friend class ComponentDefinition;
|
||||
|
||||
// ComponentHandle<ComponentInstance> is in fact a VRc<ComponentVTable, ErasedComponentBox>
|
||||
const cbindgen_private::ErasedComponentBox *inner() const
|
||||
{ return reinterpret_cast<const cbindgen_private::ErasedComponentBox *>(this); }
|
||||
|
||||
public:
|
||||
void show() const
|
||||
{
|
||||
cbindgen_private::sixtyfps_interpreter_component_instance_show(&inner, true);
|
||||
cbindgen_private::sixtyfps_interpreter_component_instance_show(inner(), true);
|
||||
}
|
||||
void hide() const
|
||||
{
|
||||
cbindgen_private::sixtyfps_interpreter_component_instance_show(&inner, false);
|
||||
cbindgen_private::sixtyfps_interpreter_component_instance_show(inner(), false);
|
||||
}
|
||||
void run() const
|
||||
{
|
||||
|
@ -376,14 +389,14 @@ public:
|
|||
{
|
||||
using namespace cbindgen_private;
|
||||
return sixtyfps_interpreter_component_instance_set_property(
|
||||
&inner, sixtyfps::private_api::string_to_slice(name), &value.inner);
|
||||
inner(), sixtyfps::private_api::string_to_slice(name), &value.inner);
|
||||
}
|
||||
std::optional<Value> get_property(std::string_view name) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
ValueOpaque out;
|
||||
if (sixtyfps_interpreter_component_instance_get_property(
|
||||
&inner, sixtyfps::private_api::string_to_slice(name), &out)) {
|
||||
inner(), sixtyfps::private_api::string_to_slice(name), &out)) {
|
||||
return Value(out);
|
||||
} else {
|
||||
return {};
|
||||
|
@ -396,7 +409,7 @@ public:
|
|||
Slice<ValueOpaque> args_view { reinterpret_cast<ValueOpaque *>(args.ptr), args.len };
|
||||
ValueOpaque out;
|
||||
if (sixtyfps_interpreter_component_instance_invoke_callback(
|
||||
&inner, sixtyfps::private_api::string_to_slice(name), args_view, &out)) {
|
||||
inner(), sixtyfps::private_api::string_to_slice(name), args_view, &out)) {
|
||||
return Value(out);
|
||||
} else {
|
||||
return {};
|
||||
|
@ -413,7 +426,7 @@ public:
|
|||
new (ret) Value(std::move(r));
|
||||
};
|
||||
return cbindgen_private::sixtyfps_interpreter_component_instance_set_callback(
|
||||
&inner, sixtyfps::private_api::string_to_slice(name), actual_cb,
|
||||
inner(), sixtyfps::private_api::string_to_slice(name), actual_cb,
|
||||
new F(std::move(callback)), [](void *data) { delete reinterpret_cast<F *>(data); });
|
||||
}
|
||||
};
|
||||
|
@ -447,6 +460,19 @@ public:
|
|||
return *this;
|
||||
}
|
||||
~ComponentDefinition() { sixtyfps_interpreter_component_definition_destructor(&inner); }
|
||||
}
|
||||
|
||||
ComponentHandle<ComponentInstance> create() const {
|
||||
union CI {
|
||||
cbindgen_private::ComponentInstance i;
|
||||
~CI() {
|
||||
i.~ComponentInstance();
|
||||
}
|
||||
CI() {}
|
||||
} u;
|
||||
cbindgen_private::sixtyfps_interpreter_component_instance_create(&inner, &u.i);
|
||||
return *reinterpret_cast<ComponentHandle<ComponentInstance> *>(&u.i);
|
||||
|
||||
};
|
||||
|
||||
class ComponentCompiler
|
||||
|
|
|
@ -765,6 +765,8 @@ pub mod testing {
|
|||
#[cfg(feature = "ffi")]
|
||||
#[allow(missing_docs)]
|
||||
pub(crate) mod ffi {
|
||||
use crate::dynamic_component::ErasedComponentBox;
|
||||
|
||||
use super::*;
|
||||
use sixtyfps_corelib::model::{Model, ModelNotify, ModelPeer};
|
||||
use sixtyfps_corelib::slice::Slice;
|
||||
|
@ -1073,11 +1075,13 @@ pub(crate) mod ffi {
|
|||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_interpreter_component_instance_get_property(
|
||||
inst: &ComponentInstance,
|
||||
inst: &ErasedComponentBox,
|
||||
name: Slice<u8>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
match inst.get_property(std::str::from_utf8(&name).unwrap()) {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
match comp.description().get_property(comp.borrow(), std::str::from_utf8(&name).unwrap()) {
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
|
@ -1088,11 +1092,19 @@ pub(crate) mod ffi {
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_interpreter_component_instance_set_property(
|
||||
inst: &ComponentInstance,
|
||||
inst: &ErasedComponentBox,
|
||||
name: Slice<u8>,
|
||||
val: &ValueOpaque,
|
||||
) -> bool {
|
||||
inst.set_property(std::str::from_utf8(&name).unwrap(), val.as_value().clone()).is_ok()
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
comp.description()
|
||||
.set_property(
|
||||
comp.borrow(),
|
||||
std::str::from_utf8(&name).unwrap(),
|
||||
val.as_value().clone(),
|
||||
)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
/// Invoke a callback.
|
||||
|
@ -1100,13 +1112,19 @@ pub(crate) mod ffi {
|
|||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_interpreter_component_instance_invoke_callback(
|
||||
inst: &ComponentInstance,
|
||||
inst: &ErasedComponentBox,
|
||||
name: Slice<u8>,
|
||||
args: Slice<ValueOpaque>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
let args = std::mem::transmute::<Slice<ValueOpaque>, Slice<Value>>(args);
|
||||
match inst.invoke_callback(std::str::from_utf8(&name).unwrap(), args.as_slice()) {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
match comp.description().invoke_callback(
|
||||
comp.borrow(),
|
||||
std::str::from_utf8(&name).unwrap(),
|
||||
args.as_slice(),
|
||||
) {
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
|
@ -1119,7 +1137,7 @@ pub(crate) mod ffi {
|
|||
/// The `callback` function must initialize the `ret` (the `ret` passed to the callback is initialized and is assumed initialized after the function)
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_interpreter_component_instance_set_callback(
|
||||
inst: &ComponentInstance,
|
||||
inst: &ErasedComponentBox,
|
||||
name: Slice<u8>,
|
||||
callback: extern "C" fn(
|
||||
user_data: *mut c_void,
|
||||
|
@ -1150,22 +1168,44 @@ pub(crate) mod ffi {
|
|||
ret.assume_init()
|
||||
};
|
||||
|
||||
inst.set_callback(std::str::from_utf8(&name).unwrap(), callback).is_ok()
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
comp.description()
|
||||
.set_callback_handler(
|
||||
comp.borrow(),
|
||||
std::str::from_utf8(&name).unwrap(),
|
||||
Box::new(callback),
|
||||
)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
/// Show or hide
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_interpreter_component_instance_show(
|
||||
inst: &ComponentInstance,
|
||||
inst: &ErasedComponentBox,
|
||||
is_visible: bool,
|
||||
) {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
if is_visible {
|
||||
inst.show();
|
||||
comp.window().show();
|
||||
} else {
|
||||
inst.hide();
|
||||
comp.window().hide();
|
||||
}
|
||||
}
|
||||
|
||||
/// Instantiate an instance from a definition.
|
||||
///
|
||||
/// The `out` must be uninitialized and is going to be initialized after the call
|
||||
/// and need to be destroyed with sixtyfps_interpreter_component_instance_destructor
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_interpreter_component_instance_create(
|
||||
def: &ComponentDefinitionOpaque,
|
||||
out: *mut ComponentInstance,
|
||||
) {
|
||||
std::ptr::write(out, def.as_component_definition().create())
|
||||
}
|
||||
|
||||
#[vtable::vtable]
|
||||
#[repr(C)]
|
||||
pub struct ModelAdaptorVTable {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue