diff --git a/sixtyfps_runtime/corelib/graphics.rs b/sixtyfps_runtime/corelib/graphics.rs index 59ae81081..1c8c50e7d 100644 --- a/sixtyfps_runtime/corelib/graphics.rs +++ b/sixtyfps_runtime/corelib/graphics.rs @@ -325,7 +325,7 @@ pub trait GraphicsBackend: Sized { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem, Clone, Debug, PartialEq)] +#[derive(FieldOffsets, Default, SixtyFPSElement, Clone, Debug, PartialEq)] #[pin] /// PathLineTo describes the event of moving the cursor on the path to the specified location /// along a straight line. @@ -339,7 +339,7 @@ pub struct PathLineTo { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem, Clone, Debug, PartialEq)] +#[derive(FieldOffsets, Default, SixtyFPSElement, Clone, Debug, PartialEq)] #[pin] /// PathArcTo describes the event of moving the cursor on the path across an arc to the specified /// x/y coordinates, with the specified x/y radius and additional properties. diff --git a/sixtyfps_runtime/corelib/items.rs b/sixtyfps_runtime/corelib/items.rs index 68c1d2837..48d5a4a8b 100644 --- a/sixtyfps_runtime/corelib/items.rs +++ b/sixtyfps_runtime/corelib/items.rs @@ -136,7 +136,7 @@ impl ItemWeak { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem, GeneratePropertyAccessors)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] /// The implementation of the `Rectangle` element pub struct Rectangle { @@ -198,7 +198,7 @@ ItemVTable_static! { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem, GeneratePropertyAccessors)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] /// The implementation of the `BorderRectangle` element pub struct BorderRectangle { @@ -276,7 +276,7 @@ ItemVTable_static! { /// The implementation of the `TouchArea` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct TouchArea { pub x: Property, @@ -373,7 +373,7 @@ ItemVTable_static! { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] /// The implementation of the `Clip` element pub struct Clip { @@ -433,7 +433,7 @@ ItemVTable_static! { /// The implementation of the `Path` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct Path { pub x: Property, @@ -496,7 +496,7 @@ ItemVTable_static! { /// The implementation of the `Flickable` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct Flickable { pub x: Property, @@ -604,7 +604,7 @@ pub unsafe extern "C" fn sixtyfps_flickable_data_free(data: *mut FlickableDataBo /// The implementation of the `PropertyAnimation` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem, Clone, Debug)] +#[derive(FieldOffsets, Default, SixtyFPSElement, Clone, Debug)] #[pin] pub struct PropertyAnimation { #[rtti_field] @@ -617,7 +617,7 @@ pub struct PropertyAnimation { /// The implementation of the `Window` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct Window { pub width: Property, diff --git a/sixtyfps_runtime/corelib/items/image.rs b/sixtyfps_runtime/corelib/items/image.rs index 8ee0a9d46..3dbbccb5b 100644 --- a/sixtyfps_runtime/corelib/items/image.rs +++ b/sixtyfps_runtime/corelib/items/image.rs @@ -50,7 +50,7 @@ impl Default for ImageFit { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] /// The implementation of the `Image` element pub struct Image { @@ -108,7 +108,7 @@ impl ItemConsts for Image { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] /// The implementation of the `ClippedImage` element pub struct ClippedImage { diff --git a/sixtyfps_runtime/corelib/items/text.rs b/sixtyfps_runtime/corelib/items/text.rs index 7666d9211..a2b52b8e0 100644 --- a/sixtyfps_runtime/corelib/items/text.rs +++ b/sixtyfps_runtime/corelib/items/text.rs @@ -71,7 +71,7 @@ const DEFAULT_FONT_WEIGHT: i32 = 400; /// The implementation of the `Text` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct Text { pub text: Property, @@ -139,14 +139,6 @@ impl ItemConsts for Text { } impl Text { - fn font_family(self: Pin<&Self>) -> SharedString { - Self::FIELD_OFFSETS.font_family.apply_pin(self).get() - } - - fn font_weight(self: Pin<&Self>) -> i32 { - Self::FIELD_OFFSETS.font_weight.apply_pin(self).get() - } - pub fn font_pixel_size(self: Pin<&Self>, scale_factor: f32) -> f32 { let font_size = Self::FIELD_OFFSETS.font_size.apply_pin(self).get(); if font_size == 0.0 { @@ -180,7 +172,7 @@ impl Text { /// The implementation of the `TextInput` element #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct TextInput { pub text: Property, @@ -562,14 +554,6 @@ impl TextInput { } } - fn font_family(self: Pin<&Self>) -> SharedString { - Self::FIELD_OFFSETS.font_family.apply_pin(self).get() - } - - fn font_weight(self: Pin<&Self>) -> i32 { - Self::FIELD_OFFSETS.font_weight.apply_pin(self).get() - } - fn font_pixel_size(self: Pin<&Self>, scale_factor: f32) -> f32 { let font_size = Self::FIELD_OFFSETS.font_size.apply_pin(self).get(); if font_size == 0.0 { diff --git a/sixtyfps_runtime/corelib_macros/lib.rs b/sixtyfps_runtime/corelib_macros/lib.rs index 3b14efb7f..fd01df72a 100644 --- a/sixtyfps_runtime/corelib_macros/lib.rs +++ b/sixtyfps_runtime/corelib_macros/lib.rs @@ -16,8 +16,14 @@ extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; -#[proc_macro_derive(BuiltinItem, attributes(rtti_field))] -pub fn builtin_item(input: TokenStream) -> TokenStream { +/// This derive macro is used with structures in the run-time library that are meant +/// to be exposed to the language. The structure is introspected for properties and fields +/// marked with the `rtti_field` attribute and generates run-time type information for use +/// with the interpeter. +/// In addition all `Property foo` fields get a convenient getter function generated +/// that works on a `Pin<&Self>` receiver. +#[proc_macro_derive(SixtyFPSElement, attributes(rtti_field))] +pub fn sixtyfps_element(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); let fields = match &input.data { @@ -32,11 +38,23 @@ pub fn builtin_item(input: TokenStream) -> TokenStream { } }; - let (prop_field_names, prop_field_types): (Vec<_>, Vec<_>) = fields - .iter() - .filter(|f| is_property(&f.ty) && matches!(f.vis, syn::Visibility::Public(_))) - .map(|f| (f.ident.as_ref().unwrap(), &f.ty)) - .unzip(); + let mut pub_prop_field_names = Vec::new(); + let mut pub_prop_field_types = Vec::new(); + let mut property_names = Vec::new(); + let mut property_visibility = Vec::new(); + let mut property_types = Vec::new(); + for field in fields { + if let Some(property_type) = property_type(&field.ty) { + let name = field.ident.as_ref().unwrap(); + if matches!(field.vis, syn::Visibility::Public(_)) { + pub_prop_field_names.push(name); + pub_prop_field_types.push(&field.ty); + } + property_names.push(name); + property_visibility.push(field.vis.clone()); + property_types.push(property_type); + } + } let (plain_field_names, plain_field_types): (Vec<_>, Vec<_>) = fields .iter() @@ -73,9 +91,9 @@ pub fn builtin_item(input: TokenStream) -> TokenStream { } fn properties() -> Vec<(&'static str, &'static dyn PropertyInfo)> { vec![#( { - const O : MaybeAnimatedPropertyInfoWrapper<#item_name, #prop_field_types> = - MaybeAnimatedPropertyInfoWrapper(#item_name::FIELD_OFFSETS.#prop_field_names); - (stringify!(#prop_field_names), (&O).as_property_info()) + const O : MaybeAnimatedPropertyInfoWrapper<#item_name, #pub_prop_field_types> = + MaybeAnimatedPropertyInfoWrapper(#item_name::FIELD_OFFSETS.#pub_prop_field_names); + (stringify!(#pub_prop_field_names), (&O).as_property_info()) } ),*] } fn fields() -> Vec<(&'static str, &'static dyn FieldInfo)> { @@ -91,6 +109,14 @@ pub fn builtin_item(input: TokenStream) -> TokenStream { ),*] } } + + impl #item_name { + #( + #property_visibility fn #property_names(self: core::pin::Pin<&Self>) -> #property_types { + Self::FIELD_OFFSETS.#property_names.apply_pin(self).get() + } + )* + } ) .into() } @@ -99,10 +125,6 @@ fn type_name(ty: &syn::Type) -> String { quote!(#ty).to_string() } -fn is_property(ty: &syn::Type) -> bool { - type_name(ty).starts_with("Property <") -} - // Try to match `Property` on the syn tree and return Foo if found fn property_type(ty: &syn::Type) -> Option<&syn::Type> { if let syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. }, .. }) = ty { @@ -155,46 +177,3 @@ pub fn keycode_mapping(input: TokenStream) -> TokenStream { ) .into() } - -#[proc_macro_derive(GeneratePropertyAccessors)] -pub fn generate_property_accessors(input: TokenStream) -> TokenStream { - let input = syn::parse_macro_input!(input as syn::DeriveInput); - - let fields = match &input.data { - syn::Data::Struct(syn::DataStruct { fields: f @ syn::Fields::Named(..), .. }) => f, - _ => { - return syn::Error::new( - input.ident.span(), - "Only `struct` with named field are supported", - ) - .to_compile_error() - .into() - } - }; - - let (prop_field_names, prop_field_types): (Vec<_>, Vec<_>) = fields - .iter() - .filter_map(|field| { - property_type(&field.ty).and_then(|prop_type| { - if matches!(field.vis, syn::Visibility::Public(_)) { - Some((field.ident.as_ref().unwrap(), prop_type)) - } else { - None - } - }) - }) - .unzip(); - - let item_name = &input.ident; - - quote!( - impl #item_name { - #( - pub fn #prop_field_names(self: Pin<&Self>) -> #prop_field_types { - Self::FIELD_OFFSETS.#prop_field_names.apply_pin(self).get() - } - )* - } - ) - .into() -} diff --git a/sixtyfps_runtime/rendering_backends/qt/widgets.rs b/sixtyfps_runtime/rendering_backends/qt/widgets.rs index b00d1902a..1901e2353 100644 --- a/sixtyfps_runtime/rendering_backends/qt/widgets.rs +++ b/sixtyfps_runtime/rendering_backends/qt/widgets.rs @@ -127,7 +127,7 @@ cpp! {{ }} #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeButton { pub x: Property, @@ -248,7 +248,7 @@ impl ItemConsts for NativeButton { ItemVTable_static! { #[no_mangle] pub static NativeButtonVTable for NativeButton } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeCheckBox { pub x: Property, @@ -364,7 +364,7 @@ struct NativeSpinBoxData { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeSpinBox { pub x: Property, @@ -574,7 +574,7 @@ struct NativeSliderData { } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeSlider { pub x: Property, @@ -768,7 +768,7 @@ impl ItemConsts for NativeSlider { ItemVTable_static! { #[no_mangle] pub static NativeSliderVTable for NativeSlider } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeGroupBox { pub x: Property, @@ -961,7 +961,7 @@ impl ItemConsts for NativeGroupBox { ItemVTable_static! { #[no_mangle] pub static NativeGroupBoxVTable for NativeGroupBox } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeLineEdit { pub x: Property, @@ -1101,7 +1101,7 @@ impl ItemConsts for NativeLineEdit { ItemVTable_static! { #[no_mangle] pub static NativeLineEditVTable for NativeLineEdit } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeScrollView { pub x: Property, @@ -1470,7 +1470,7 @@ impl ItemConsts for NativeScrollView { ItemVTable_static! { #[no_mangle] pub static NativeScrollViewVTable for NativeScrollView } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeStandardListViewItem { pub x: Property, @@ -1585,7 +1585,7 @@ impl ItemConsts for NativeStandardListViewItem { ItemVTable_static! { #[no_mangle] pub static NativeStandardListViewItemVTable for NativeStandardListViewItem } #[repr(C)] -#[derive(FieldOffsets, Default, BuiltinItem)] +#[derive(FieldOffsets, Default, SixtyFPSElement)] #[pin] pub struct NativeComboBox { pub x: Property, @@ -1717,7 +1717,7 @@ impl ItemConsts for NativeComboBox { ItemVTable_static! { #[no_mangle] pub static NativeComboBoxVTable for NativeComboBox } #[repr(C)] -#[derive(FieldOffsets, BuiltinItem)] +#[derive(FieldOffsets, SixtyFPSElement)] #[pin] pub struct NativeStyleMetrics { pub layout_spacing: Property,