mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Begin passing the VRC<ComponentVTable, Dyn> into the run-time library
First by changing the signature of run() and by adding a self_weak to the C++ struct.
This commit is contained in:
parent
a9791c390d
commit
5d744c86c2
11 changed files with 97 additions and 56 deletions
|
@ -72,8 +72,9 @@ using cbindgen_private::TraversalOrder;
|
|||
namespace private_api {
|
||||
using ItemTreeNode = cbindgen_private::ItemTreeNode<uint8_t>;
|
||||
|
||||
struct ComponentWindow
|
||||
class ComponentWindow
|
||||
{
|
||||
public:
|
||||
ComponentWindow() { cbindgen_private::sixtyfps_component_window_init(&inner); }
|
||||
~ComponentWindow() { cbindgen_private::sixtyfps_component_window_drop(&inner); }
|
||||
ComponentWindow(const ComponentWindow &) = delete;
|
||||
|
@ -83,8 +84,9 @@ struct ComponentWindow
|
|||
template<typename Component>
|
||||
void run(const Component *c) const
|
||||
{
|
||||
sixtyfps_component_window_run(
|
||||
&inner, vtable::VRefMut<ComponentVTable> { &Component::component_type, const_cast<Component *>(c) });
|
||||
auto self_rc = c->self_weak.lock().value();
|
||||
sixtyfps_component_window_run(&inner,
|
||||
reinterpret_cast<cbindgen_private::ComponentRc *>(&self_rc));
|
||||
}
|
||||
|
||||
float scale_factor() const { return sixtyfps_component_window_get_scale_factor(&inner); }
|
||||
|
@ -129,6 +131,7 @@ using cbindgen_private::Window;
|
|||
|
||||
using cbindgen_private::NativeButton;
|
||||
using cbindgen_private::NativeCheckBox;
|
||||
using cbindgen_private::NativeComboBox;
|
||||
using cbindgen_private::NativeGroupBox;
|
||||
using cbindgen_private::NativeLineEdit;
|
||||
using cbindgen_private::NativeScrollView;
|
||||
|
@ -136,7 +139,6 @@ using cbindgen_private::NativeSlider;
|
|||
using cbindgen_private::NativeSpinBox;
|
||||
using cbindgen_private::NativeStandardListViewItem;
|
||||
using cbindgen_private::NativeStyleMetrics;
|
||||
using cbindgen_private::NativeComboBox;
|
||||
|
||||
namespace private_api {
|
||||
constexpr inline ItemTreeNode make_item_node(std::uintptr_t offset,
|
||||
|
@ -153,9 +155,10 @@ constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset)
|
|||
offset } };
|
||||
}
|
||||
|
||||
inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tree, int index) {
|
||||
inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tree, int index)
|
||||
{
|
||||
const auto &item = item_tree.ptr[index].item.item;
|
||||
return ItemRef { item.vtable, reinterpret_cast<char*>(component.instance) + item.offset };
|
||||
return ItemRef { item.vtable, reinterpret_cast<char *>(component.instance) + item.offset };
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -276,50 +279,55 @@ inline FocusEventResult process_focus_event(ComponentRef component, int64_t &foc
|
|||
return FocusEventResult::FocusItemNotFound;
|
||||
}
|
||||
|
||||
void dealloc(const ComponentVTable*, uint8_t *ptr, vtable::Layout layout) {
|
||||
void dealloc(const ComponentVTable *, uint8_t *ptr, vtable::Layout layout)
|
||||
{
|
||||
#ifdef __cpp_sized_deallocation
|
||||
::operator delete(reinterpret_cast<void*>(ptr), layout.size, static_cast<std::align_val_t>(layout.align));
|
||||
::operator delete(reinterpret_cast<void *>(ptr), layout.size,
|
||||
static_cast<std::align_val_t>(layout.align));
|
||||
#else
|
||||
::operator delete(reinterpret_cast<void*>(ptr), static_cast<std::align_val_t>(layout.align));
|
||||
::operator delete(reinterpret_cast<void *>(ptr), static_cast<std::align_val_t>(layout.align));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
template<typename T> vtable::Layout drop_in_place(ComponentRef component) {
|
||||
reinterpret_cast<T*>(component.instance)->~T();
|
||||
template<typename T>
|
||||
vtable::Layout drop_in_place(ComponentRef component)
|
||||
{
|
||||
reinterpret_cast<T *>(component.instance)->~T();
|
||||
return vtable::Layout { sizeof(T), alignof(T) };
|
||||
}
|
||||
} // namespace private_api
|
||||
|
||||
template<typename T> class ComponentWeakHandle;
|
||||
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 .60 file. This give you a `ComponentHandle<T>`
|
||||
template<typename T>
|
||||
class ComponentHandle {
|
||||
class ComponentHandle
|
||||
{
|
||||
vtable::VRc<private_api::ComponentVTable, T> inner;
|
||||
friend class ComponentWeakHandle<T>;
|
||||
|
||||
public:
|
||||
/// internal constructor
|
||||
ComponentHandle(const vtable::VRc<private_api::ComponentVTable, T> &inner) : inner(inner) { }
|
||||
|
||||
const T* operator->() const {
|
||||
return inner.operator->();
|
||||
}
|
||||
const T& operator*() const {
|
||||
return inner.operator*();
|
||||
}
|
||||
const T *operator->() const { return inner.operator->(); }
|
||||
const T &operator*() const { return inner.operator*(); }
|
||||
};
|
||||
|
||||
/// A weak reference to the component. Can be constructed from a `ComponentHandle<T>`
|
||||
template<typename T>
|
||||
class ComponentWeakHandle {
|
||||
class ComponentWeakHandle
|
||||
{
|
||||
vtable::VWeak<private_api::ComponentVTable, T> inner;
|
||||
|
||||
public:
|
||||
ComponentWeakHandle() = default;
|
||||
ComponentWeakHandle(const ComponentHandle<T>&other) : inner(other.inner) {}
|
||||
std::optional<ComponentHandle<T>> lock() const {
|
||||
ComponentWeakHandle(const ComponentHandle<T> &other) : inner(other.inner) { }
|
||||
std::optional<ComponentHandle<T>> lock() const
|
||||
{
|
||||
if (auto l = inner.lock()) {
|
||||
return { ComponentHandle(*l) };
|
||||
} else {
|
||||
|
@ -329,32 +337,31 @@ public:
|
|||
};
|
||||
|
||||
// layouts:
|
||||
using cbindgen_private::box_layout_info;
|
||||
using cbindgen_private::BoxLayoutCellData;
|
||||
using cbindgen_private::BoxLayoutData;
|
||||
using cbindgen_private::grid_layout_info;
|
||||
using cbindgen_private::GridLayoutCellData;
|
||||
using cbindgen_private::GridLayoutData;
|
||||
using cbindgen_private::BoxLayoutData;
|
||||
using cbindgen_private::BoxLayoutCellData;
|
||||
using cbindgen_private::LayoutAlignment;
|
||||
using cbindgen_private::LayoutInfo;
|
||||
using cbindgen_private::Padding;
|
||||
using cbindgen_private::PathLayoutData;
|
||||
using cbindgen_private::PathLayoutItemData;
|
||||
using cbindgen_private::solve_grid_layout;
|
||||
using cbindgen_private::solve_box_layout;
|
||||
using cbindgen_private::box_layout_info;
|
||||
using cbindgen_private::solve_path_layout;
|
||||
using cbindgen_private::Rect;
|
||||
using cbindgen_private::LayoutAlignment;
|
||||
using cbindgen_private::solve_box_layout;
|
||||
using cbindgen_private::solve_grid_layout;
|
||||
using cbindgen_private::solve_path_layout;
|
||||
|
||||
inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const {
|
||||
inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const
|
||||
{
|
||||
// Note: This "logic" is duplicated from LayoutInfo::merge in layout.rs.
|
||||
return LayoutInfo {
|
||||
std::max(min_width, other.min_width),
|
||||
return LayoutInfo { std::max(min_width, other.min_width),
|
||||
std::min(max_width, other.max_width),
|
||||
std::max(min_height, other.min_height),
|
||||
std::min(max_height, other.max_height),
|
||||
std::min(horizontal_stretch, other.horizontal_stretch),
|
||||
std::min(vertical_stretch, other.vertical_stretch)
|
||||
};
|
||||
std::min(vertical_stretch, other.vertical_stretch) };
|
||||
}
|
||||
|
||||
// models
|
||||
|
@ -591,7 +598,7 @@ public:
|
|||
vtable::VRef<private_api::ComponentVTable> item_at(int i) const
|
||||
{
|
||||
const auto &x = inner->data.at(i);
|
||||
return { &C::component_type, const_cast<C*>(&(**x.ptr)) };
|
||||
return { &C::component_type, const_cast<C *>(&(**x.ptr)) };
|
||||
}
|
||||
|
||||
void compute_layout(cbindgen_private::Rect parent_rect) const
|
||||
|
@ -599,7 +606,8 @@ public:
|
|||
if (!inner)
|
||||
return;
|
||||
for (auto &x : inner->data) {
|
||||
(*x.ptr)->apply_layout({ &C::component_type, const_cast<C*>(&(**x.ptr)) }, parent_rect);
|
||||
(*x.ptr)->apply_layout({ &C::component_type, const_cast<C *>(&(**x.ptr)) },
|
||||
parent_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,17 +649,21 @@ Flickable::~Flickable()
|
|||
sixtyfps_flickable_data_free(&data);
|
||||
}
|
||||
|
||||
NativeStyleMetrics::NativeStyleMetrics() {
|
||||
NativeStyleMetrics::NativeStyleMetrics()
|
||||
{
|
||||
sixtyfps_init_native_style_metrics(this);
|
||||
}
|
||||
|
||||
using cbindgen_private::StandardListViewItem;
|
||||
namespace cbindgen_private {
|
||||
bool operator==(const StandardListViewItem &a, const StandardListViewItem &b) {
|
||||
static_assert(sizeof(StandardListViewItem) == sizeof(std::tuple<SharedString>), "must update to cover all fields");
|
||||
bool operator==(const StandardListViewItem &a, const StandardListViewItem &b)
|
||||
{
|
||||
static_assert(sizeof(StandardListViewItem) == sizeof(std::tuple<SharedString>),
|
||||
"must update to cover all fields");
|
||||
return a.text == b.text;
|
||||
}
|
||||
bool operator!=(const StandardListViewItem &a, const StandardListViewItem &b) {
|
||||
bool operator!=(const StandardListViewItem &a, const StandardListViewItem &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ declare_types! {
|
|||
let component = cx.borrow(&mut this, |x| x.0.clone());
|
||||
let component = component.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
run_scoped(&mut cx,this.downcast().unwrap(), || {
|
||||
component.window().run(component.borrow());
|
||||
component.window().run(&vtable::VRc::into_dyn(component));
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
|
|
|
@ -19,6 +19,7 @@ wasm-bindgen-futures = { version = "0.4.18" }
|
|||
js-sys = "0.3.44"
|
||||
console_error_panic_hook = { version = "0.1.6", optional = true }
|
||||
wee_alloc = { version = "0.4.5", optional = true }
|
||||
vtable = { version = "0.1.1", path="../../helper_crates/vtable" }
|
||||
|
||||
#[dev-dependencies]
|
||||
#wasm-bindgen-test = "0.3.13"
|
||||
|
|
|
@ -127,6 +127,6 @@ impl WrappedCompiledComp {
|
|||
#[wasm_bindgen]
|
||||
pub fn run(&self, canvas_id: String) {
|
||||
let component = self.0.clone().create(canvas_id);
|
||||
component.window().run(component.borrow());
|
||||
component.window().run(&vtable::VRc::into_dyn(component));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -830,6 +830,18 @@ fn generate_component(
|
|||
}),
|
||||
));
|
||||
|
||||
component_struct.members.push((
|
||||
Access::Private,
|
||||
Declaration::Var(Var {
|
||||
ty: format!(
|
||||
"vtable::VWeak<sixtyfps::private_api::ComponentVTable, {}>",
|
||||
component_id
|
||||
),
|
||||
name: "self_weak".into(),
|
||||
..Var::default()
|
||||
}),
|
||||
));
|
||||
|
||||
component_struct.members.push((
|
||||
Access::Public,
|
||||
Declaration::Function(Function {
|
||||
|
@ -845,13 +857,18 @@ fn generate_component(
|
|||
window = window_ref_expression(component)
|
||||
));
|
||||
|
||||
component_struct.friends.push("sixtyfps::private_api::ComponentWindow".into());
|
||||
|
||||
component_struct.members.push((
|
||||
Access::Public,
|
||||
Declaration::Function(Function {
|
||||
name: "create".into(),
|
||||
signature: format!("() -> sixtyfps::ComponentHandle<{}>", component_id),
|
||||
statements: Some(vec![format!(
|
||||
"return sixtyfps::ComponentHandle<{0}>{{ vtable::VRc<sixtyfps::private_api::ComponentVTable, {0}>::make() }};",
|
||||
statements: Some(vec![
|
||||
format!("auto self_rc = vtable::VRc<sixtyfps::private_api::ComponentVTable, {0}>::make();", component_id),
|
||||
format!("const_cast<{0} *>(&*self_rc)->self_weak = vtable::VWeak(self_rc);", component_id),
|
||||
format!(
|
||||
"return sixtyfps::ComponentHandle<{0}>{{ self_rc }};",
|
||||
component_id,
|
||||
)]),
|
||||
is_static: true,
|
||||
|
|
|
@ -583,7 +583,7 @@ fn generate_component(
|
|||
impl sixtyfps::Component for #component_id {
|
||||
fn run(self: ::core::pin::Pin<&Self>) {
|
||||
use sixtyfps::re_exports::*;
|
||||
self.as_ref().window.run(VRef::new_pin(self.as_ref()));
|
||||
self.as_ref().window.run(&VRc::into_dyn(self.as_ref().self_weak.get().unwrap().upgrade().unwrap()));
|
||||
}
|
||||
}
|
||||
))
|
||||
|
|
|
@ -79,9 +79,12 @@ pub struct ComponentVTable {
|
|||
/// the associated vtable
|
||||
pub type ComponentRef<'a> = vtable::VRef<'a, ComponentVTable>;
|
||||
|
||||
/// Type alias to the commonly use `Pin<VRef<ComponentVTable>>>`
|
||||
/// Type alias to the commonly used `Pin<VRef<ComponentVTable>>>`
|
||||
pub type ComponentRefPin<'a> = core::pin::Pin<ComponentRef<'a>>;
|
||||
|
||||
/// Type alias to the commonly used VRc<ComponentVTable, Dyn>>
|
||||
pub type ComponentRc = vtable::VRc<ComponentVTable, Dyn>;
|
||||
|
||||
/// Call init() on the ItemVTable for each item of the component.
|
||||
pub fn init_component_items<Base>(
|
||||
base: core::pin::Pin<&Base>,
|
||||
|
|
|
@ -13,7 +13,7 @@ LICENSE END */
|
|||
[GenericWindow] trait used by the generated code and the run-time to change
|
||||
aspects of windows on the screen.
|
||||
*/
|
||||
use crate::component::ComponentVTable;
|
||||
use crate::component::{ComponentRc, ComponentVTable};
|
||||
use std::cell::RefCell;
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
|
@ -143,9 +143,11 @@ impl ComponentWindow {
|
|||
Self(window_impl)
|
||||
}
|
||||
/// Spins an event loop and renders the items of the provided component in this window.
|
||||
pub fn run(&self, component: Pin<VRef<ComponentVTable>>) {
|
||||
pub fn run(&self, component: &ComponentRc) {
|
||||
let event_loop = crate::eventloop::EventLoop::new();
|
||||
|
||||
let component = ComponentRc::borrow_pin(component);
|
||||
|
||||
self.0.clone().map_window(&event_loop, component);
|
||||
|
||||
event_loop.run(component);
|
||||
|
@ -583,7 +585,7 @@ pub mod ffi {
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_component_window_run(
|
||||
handle: *const ComponentWindowOpaque,
|
||||
component: Pin<VRef<ComponentVTable>>,
|
||||
component: &ComponentRc,
|
||||
) {
|
||||
let window = &*(handle as *const ComponentWindow);
|
||||
window.run(component);
|
||||
|
|
|
@ -68,6 +68,12 @@ impl<'id> ComponentBox<'id> {
|
|||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn run(self) {
|
||||
let rc_box = vtable::VRc::new(ErasedComponentBox::from(self));
|
||||
let window = rc_box.0.window();
|
||||
window.run(&vtable::VRc::into_dyn(rc_box));
|
||||
}
|
||||
}
|
||||
|
||||
impl<'id> Drop for ComponentBox<'id> {
|
||||
|
|
|
@ -217,7 +217,7 @@ fn gen_corelib(include_dir: &Path) -> anyhow::Result<()> {
|
|||
.with_after_include(format!(
|
||||
r"
|
||||
namespace sixtyfps {{
|
||||
namespace private_api {{ enum class VersionCheck {{ Major = {}, Minor = {}, Patch = {} }}; struct ComponentWindow; }}
|
||||
namespace private_api {{ enum class VersionCheck {{ Major = {}, Minor = {}, Patch = {} }}; class ComponentWindow; }}
|
||||
namespace cbindgen_private {{ using sixtyfps::private_api::ComponentWindow; using namespace vtable; }}
|
||||
}}",
|
||||
0, 0, 2,
|
||||
|
|
|
@ -44,6 +44,6 @@ fn main() -> std::io::Result<()> {
|
|||
};
|
||||
|
||||
let component = c.create();
|
||||
component.window().run(component.borrow());
|
||||
component.window().run(&vtable::VRc::into_dyn(component));
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue