Visit the item as Pin

A preparation to have Property::get to take Pin<Self>
This commit is contained in:
Olivier Goffart 2020-06-25 18:50:20 +02:00
parent 40f4265071
commit 1b748792ad
8 changed files with 86 additions and 48 deletions

View file

@ -472,6 +472,18 @@ impl<Base, T: ?Sized + VTableMeta, Flag> VOffset<Base, T, Flag> {
}
}
impl<Base, T: ?Sized + VTableMeta> VOffset<Base, T, PinnedFlag> {
pub fn apply_pin<'a>(self, x: Pin<&'a Base>) -> Pin<VRef<'a, T>> {
let ptr = x.get_ref() as *const Base as *mut u8;
unsafe {
Pin::new_unchecked(VRef::from_raw(
NonNull::from(self.vtable),
NonNull::new_unchecked(ptr.add(self.offset)),
))
}
}
}
// Need to implement manually otheriwse it is not implemented if T do not implement Copy / Clone
impl<Base, T: ?Sized + VTableMeta, Flag> Copy for VOffset<Base, T, Flag> {}

View file

@ -277,7 +277,7 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
#(#repeated_element_names : sixtyfps::re_exports::Repeater<#repeated_element_components>,)*
}
impl core::default::Default for #component_id {
impl ::core::default::Default for #component_id {
fn default() -> Self {
#![allow(unused)]
use sixtyfps::re_exports::*;
@ -294,12 +294,12 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
}
impl sixtyfps::re_exports::Component for #component_id {
fn visit_children_item(self: core::pin::Pin<&Self>, index: isize, visitor: sixtyfps::re_exports::ItemVisitorRefMut) {
fn visit_children_item(self: ::core::pin::Pin<&Self>, index: isize, visitor: sixtyfps::re_exports::ItemVisitorRefMut) {
use sixtyfps::re_exports::*;
let tree = &[#(#item_tree_array),*];
sixtyfps::re_exports::visit_item_tree(self.get_ref(), VRef::new_pin(self), tree, index, visitor, visit_dynamic);
sixtyfps::re_exports::visit_item_tree(self, VRef::new_pin(self), tree, index, visitor, visit_dynamic);
#[allow(unused)]
fn visit_dynamic(base: &#component_id, visitor: ItemVisitorRefMut, dyn_index: usize) {
fn visit_dynamic(base: ::core::pin::Pin<&#component_id>, visitor: ItemVisitorRefMut, dyn_index: usize) {
match dyn_index {
#(#repeated_visit_branch)*
_ => panic!("invalid dyn_index {}", dyn_index),
@ -604,10 +604,10 @@ fn compute_layout(component: &Component) -> TokenStream {
}
quote! {
fn layout_info(self: core::pin::Pin<&Self>) -> sixtyfps::re_exports::LayoutInfo {
fn layout_info(self: ::core::pin::Pin<&Self>) -> sixtyfps::re_exports::LayoutInfo {
todo!("Implement in rust.rs")
}
fn compute_layout(self: core::pin::Pin<&Self>, eval_context: &sixtyfps::re_exports::EvaluationContext) {
fn compute_layout(self: ::core::pin::Pin<&Self>, eval_context: &sixtyfps::re_exports::EvaluationContext) {
#![allow(unused)]
use sixtyfps::re_exports::*;
let dummy = Property::<f32>::default();

View file

@ -106,7 +106,8 @@ pub enum ItemTreeNode<T> {
#[repr(C)]
pub struct ItemVTable {
/// Returns the geometry of this item (relative to its parent item)
pub geometry: extern "C" fn(VRef<'_, ItemVTable>, context: &crate::EvaluationContext) -> Rect,
pub geometry:
extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, context: &crate::EvaluationContext) -> Rect,
/// offset in bytes fromthe *const ItemImpl.
/// isize::MAX means None
@ -116,15 +117,16 @@ pub struct ItemVTable {
/// Return the rendering primitive used to display this item.
pub rendering_primitive: extern "C" fn(
VRef<'_, ItemVTable>,
core::pin::Pin<VRef<ItemVTable>>,
context: &crate::EvaluationContext,
) -> RenderingPrimitive,
/// We would need max/min/preferred size, and all layout info
pub layouting_info: extern "C" fn(VRef<'_, ItemVTable>) -> LayoutInfo,
pub layouting_info: extern "C" fn(core::pin::Pin<VRef<ItemVTable>>) -> LayoutInfo,
/// input event
pub input_event: extern "C" fn(VRef<'_, ItemVTable>, MouseEvent, &crate::EvaluationContext),
pub input_event:
extern "C" fn(core::pin::Pin<VRef<ItemVTable>>, MouseEvent, &crate::EvaluationContext),
}
/// The constraint that applies to an item
@ -328,19 +330,14 @@ pub struct ItemVisitorVTable {
VRefMut<ItemVisitorVTable>,
component: Pin<VRef<ComponentVTable>>,
index: isize,
item: VRef<ItemVTable>,
item: Pin<VRef<ItemVTable>>,
),
/// Destructor
drop: fn(VRefMut<ItemVisitorVTable>),
}
impl<T: FnMut(crate::ComponentRefPin, isize, VRef<ItemVTable>)> ItemVisitor for T {
fn visit_item(
&mut self,
component: crate::ComponentRefPin,
index: isize,
item: VRef<ItemVTable>,
) {
impl<T: FnMut(crate::ComponentRefPin, isize, Pin<ItemRef>)> ItemVisitor for T {
fn visit_item(&mut self, component: crate::ComponentRefPin, index: isize, item: Pin<ItemRef>) {
self(component, index, item)
}
}
@ -361,12 +358,12 @@ pub unsafe extern "C" fn sixtyfps_visit_item_tree(
),
) {
crate::item_tree::visit_item_tree(
&*(component.as_ptr() as *const u8),
Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
component,
item_tree.as_slice(),
index,
visitor,
|a, b, c| visit_dynamic(a, b, c),
|a, b, c| visit_dynamic(a.get_ref(), b, c),
)
}

View file

@ -22,6 +22,7 @@ use super::datastructures::{
use crate::rtti::*;
use crate::{EvaluationContext, Property, SharedString, Signal};
use const_field_offset::FieldOffsets;
use core::pin::Pin;
use corelib_macro::*;
#[repr(C)]
@ -39,7 +40,7 @@ pub struct Rectangle {
}
impl Item for Rectangle {
fn geometry(&self, context: &EvaluationContext) -> Rect {
fn geometry(self: Pin<&Self>, context: &EvaluationContext) -> Rect {
euclid::rect(
self.x.get(context),
self.y.get(context),
@ -47,7 +48,10 @@ impl Item for Rectangle {
self.height.get(context),
)
}
fn rendering_primitive(&self, context: &crate::EvaluationContext) -> RenderingPrimitive {
fn rendering_primitive(
self: Pin<&Self>,
context: &crate::EvaluationContext,
) -> RenderingPrimitive {
let width = self.width.get(context);
let height = self.height.get(context);
if width > 0. && height > 0. {
@ -63,11 +67,16 @@ impl Item for Rectangle {
}
}
fn layouting_info(&self) -> LayoutInfo {
fn layouting_info(self: Pin<&Self>) -> LayoutInfo {
Default::default()
}
fn input_event(&self, _: super::datastructures::MouseEvent, _: &crate::EvaluationContext) {}
fn input_event(
self: Pin<&Self>,
_: super::datastructures::MouseEvent,
_: &crate::EvaluationContext,
) {
}
}
impl ItemConsts for Rectangle {
@ -93,7 +102,7 @@ pub struct Image {
}
impl Item for Image {
fn geometry(&self, context: &crate::EvaluationContext) -> Rect {
fn geometry(self: Pin<&Self>, context: &crate::EvaluationContext) -> Rect {
euclid::rect(
self.x.get(context),
self.y.get(context),
@ -101,7 +110,10 @@ impl Item for Image {
self.height.get(context),
)
}
fn rendering_primitive(&self, context: &crate::EvaluationContext) -> RenderingPrimitive {
fn rendering_primitive(
self: Pin<&Self>,
context: &crate::EvaluationContext,
) -> RenderingPrimitive {
RenderingPrimitive::Image {
x: self.x.get(context),
y: self.y.get(context),
@ -109,12 +121,17 @@ impl Item for Image {
}
}
fn layouting_info(&self) -> LayoutInfo {
fn layouting_info(self: Pin<&Self>) -> LayoutInfo {
// FIXME: should we use the image size here
Default::default()
}
fn input_event(&self, _: super::datastructures::MouseEvent, _: &crate::EvaluationContext) {}
fn input_event(
self: Pin<&Self>,
_: super::datastructures::MouseEvent,
_: &crate::EvaluationContext,
) {
}
}
impl ItemConsts for Image {
@ -142,10 +159,13 @@ pub struct Text {
impl Item for Text {
// FIXME: width / height. or maybe it doesn't matter? (
fn geometry(&self, context: &crate::EvaluationContext) -> Rect {
fn geometry(self: Pin<&Self>, context: &crate::EvaluationContext) -> Rect {
euclid::rect(self.x.get(context), self.y.get(context), 0., 0.)
}
fn rendering_primitive(&self, context: &crate::EvaluationContext) -> RenderingPrimitive {
fn rendering_primitive(
self: Pin<&Self>,
context: &crate::EvaluationContext,
) -> RenderingPrimitive {
RenderingPrimitive::Text {
x: self.x.get(context),
y: self.y.get(context),
@ -156,11 +176,16 @@ impl Item for Text {
}
}
fn layouting_info(&self) -> LayoutInfo {
fn layouting_info(self: Pin<&Self>) -> LayoutInfo {
todo!()
}
fn input_event(&self, _: super::datastructures::MouseEvent, _: &crate::EvaluationContext) {}
fn input_event(
self: Pin<&Self>,
_: super::datastructures::MouseEvent,
_: &crate::EvaluationContext,
) {
}
}
impl ItemConsts for Text {
@ -187,7 +212,7 @@ pub struct TouchArea {
}
impl Item for TouchArea {
fn geometry(&self, context: &crate::EvaluationContext) -> Rect {
fn geometry(self: Pin<&Self>, context: &crate::EvaluationContext) -> Rect {
euclid::rect(
self.x.get(context),
self.y.get(context),
@ -195,16 +220,19 @@ impl Item for TouchArea {
self.height.get(context),
)
}
fn rendering_primitive(&self, _context: &crate::EvaluationContext) -> RenderingPrimitive {
fn rendering_primitive(
self: Pin<&Self>,
_context: &crate::EvaluationContext,
) -> RenderingPrimitive {
RenderingPrimitive::NoContents
}
fn layouting_info(&self) -> LayoutInfo {
fn layouting_info(self: Pin<&Self>) -> LayoutInfo {
todo!()
}
fn input_event(
&self,
self: Pin<&Self>,
event: super::datastructures::MouseEvent,
context: &crate::EvaluationContext,
) {

View file

@ -13,13 +13,13 @@ pub fn process_mouse_event(component: ComponentRefPin, event: MouseEvent) {
crate::item_tree::visit_items(
component,
|context, item, offset| {
let geom = item.geometry(context);
let geom = item.as_ref().geometry(context);
let geom = geom.translate(*offset);
if geom.contains(event.pos) {
let mut event2 = event.clone();
event2.pos -= geom.origin.to_vector();
item.input_event(event2, context);
item.as_ref().input_event(event2, context);
}
geom.origin.to_vector()

View file

@ -7,11 +7,11 @@ use cgmath::{Matrix4, SquareMatrix, Vector3};
pub(crate) fn update_item_rendering_data<Backend: GraphicsBackend>(
context: &EvaluationContext,
item: ItemRef<'_>,
item: core::pin::Pin<ItemRef>,
rendering_cache: &mut RenderingCache<Backend>,
rendering_primitives_builder: &mut Backend::RenderingPrimitivesBuilder,
) {
let item_rendering_primitive = item.rendering_primitive(context);
let item_rendering_primitive = item.as_ref().rendering_primitive(context);
let rendering_data = item.cached_rendering_data_offset();
@ -47,7 +47,7 @@ pub(crate) fn render_component_items<Backend: GraphicsBackend>(
crate::item_tree::visit_items(
component,
|context, item, transform| {
let origin = item.geometry(context).origin;
let origin = item.as_ref().geometry(context).origin;
let transform =
transform * Matrix4::from_translation(Vector3::new(origin.x, origin.y, 0.));

View file

@ -1,13 +1,14 @@
use crate::abi::datastructures::{ItemRef, ItemTreeNode, ItemVisitor, ItemVisitorVTable};
use crate::ComponentRefPin;
use crate::EvaluationContext;
use core::pin::Pin;
/// Visit each items recursively
///
/// The state parametter returned by the visitor is passed to each children.
pub fn visit_items<State>(
component: ComponentRefPin,
mut visitor: impl FnMut(&EvaluationContext, ItemRef, &State) -> State,
mut visitor: impl FnMut(&EvaluationContext, Pin<ItemRef>, &State) -> State,
state: State,
) {
let context = EvaluationContext::for_root_component(component);
@ -16,11 +17,11 @@ pub fn visit_items<State>(
fn visit_internal<State>(
context: &EvaluationContext,
visitor: &mut impl FnMut(&EvaluationContext, ItemRef, &State) -> State,
visitor: &mut impl FnMut(&EvaluationContext, Pin<ItemRef>, &State) -> State,
index: isize,
state: &State,
) {
let mut actual_visitor = |component: ComponentRefPin, index: isize, item: ItemRef| {
let mut actual_visitor = |component: ComponentRefPin, index: isize, item: Pin<ItemRef>| {
if component.as_ptr() == context.component.as_ptr() {
let s = visitor(context, item, state);
visit_internal(context, visitor, index, &s);
@ -43,16 +44,16 @@ fn visit_internal<State>(
/// Need to check if the compiler is able to optimize away some of it.
/// Possibly we should generate code that directly call the visitor instead
pub fn visit_item_tree<Base>(
base: &Base,
base: Pin<&Base>,
component: ComponentRefPin,
item_tree: &[ItemTreeNode<Base>],
index: isize,
mut visitor: vtable::VRefMut<ItemVisitorVTable>,
visit_dynamic: impl Fn(&Base, vtable::VRefMut<ItemVisitorVTable>, usize),
visit_dynamic: impl Fn(Pin<&Base>, vtable::VRefMut<ItemVisitorVTable>, usize),
) {
let mut visit_at_index = |idx: usize| match &item_tree[idx] {
ItemTreeNode::Item { item, .. } => {
visitor.visit_item(component, idx as isize, item.apply(base));
visitor.visit_item(component, idx as isize, item.apply_pin(base));
}
ItemTreeNode::DynamicTree { index } => visit_dynamic(base, visitor.borrow_mut(), *index),
};

View file

@ -108,7 +108,7 @@ unsafe extern "C" fn visit_children_item(
&*(component.get_vtable() as *const ComponentVTable as *const ComponentDescription);
let item_tree = &component_type.it;
sixtyfps_corelib::item_tree::visit_item_tree(
&*(component.as_ptr() as *const Instance),
Pin::new_unchecked(&*(component.as_ptr() as *const Instance)),
component,
item_tree.as_slice().into(),
index,