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:
Simon Hausmann 2020-11-11 17:47:18 +01:00
parent a9791c390d
commit 5d744c86c2
11 changed files with 97 additions and 56 deletions

View file

@ -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);
}
}

View file

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

View file

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

View file

@ -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));
}
}

View file

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

View file

@ -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()));
}
}
))

View file

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

View file

@ -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);

View file

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

View file

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

View file

@ -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(())
}