mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 22:01:13 +00:00
Move corelib::abi::properties to corelib::properties
And the bits that are only there for the C binding are now in an ffi sub-module.
This commit is contained in:
parent
b259a09338
commit
9b13b363c3
8 changed files with 269 additions and 250 deletions
|
@ -76,7 +76,6 @@ pub mod re_exports {
|
|||
pub use once_cell::unsync::OnceCell;
|
||||
pub use pin_weak::rc::*;
|
||||
pub use sixtyfps_corelib::abi::datastructures::*;
|
||||
pub use sixtyfps_corelib::abi::properties::{Property, PropertyListenerScope};
|
||||
pub use sixtyfps_corelib::abi::signals::Signal;
|
||||
pub use sixtyfps_corelib::abi::slice::Slice;
|
||||
pub use sixtyfps_corelib::animations::EasingCurve;
|
||||
|
@ -93,6 +92,7 @@ pub mod re_exports {
|
|||
grid_layout_info, solve_grid_layout, solve_path_layout, GridLayoutCellData, GridLayoutData,
|
||||
PathLayoutData, PathLayoutItemData,
|
||||
};
|
||||
pub use sixtyfps_corelib::properties::{Property, PropertyListenerScope};
|
||||
pub use sixtyfps_corelib::Color;
|
||||
pub use sixtyfps_corelib::ComponentVTable_static;
|
||||
pub use sixtyfps_corelib::Resource;
|
||||
|
|
|
@ -78,7 +78,7 @@ fn main() {
|
|||
|
||||
cbindgen::Builder::new()
|
||||
.with_config(config.clone())
|
||||
.with_src(crate_dir.join("abi/properties.rs"))
|
||||
.with_src(crate_dir.join("properties.rs"))
|
||||
.with_src(crate_dir.join("abi/signals.rs"))
|
||||
.with_after_include("namespace sixtyfps { struct Color; }")
|
||||
.generate()
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
};
|
||||
use vtable::*;
|
||||
|
||||
use crate::{graphics::Size, input::MouseEventType};
|
||||
use crate::{graphics::Size, input::MouseEventType, properties::PropertyListenerScope};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use winit::platform::desktop::EventLoopExtDesktop;
|
||||
|
||||
|
@ -87,7 +87,7 @@ impl EventLoop {
|
|||
) {
|
||||
use winit::event::Event;
|
||||
use winit::event_loop::{ControlFlow, EventLoopWindowTarget};
|
||||
let layout_listener = Rc::pin(crate::abi::properties::PropertyListenerScope::default());
|
||||
let layout_listener = Rc::pin(PropertyListenerScope::default());
|
||||
|
||||
let mut cursor_pos = winit::dpi::PhysicalPosition::new(0., 0.);
|
||||
let mut run_fn = move |event: Event<()>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
extern crate alloc;
|
||||
use crate::input::{MouseEvent, MouseEventType};
|
||||
use crate::properties::InterpolatedPropertyValue;
|
||||
#[cfg(feature = "rtti")]
|
||||
use crate::rtti::{BuiltinItem, FieldInfo, FieldOffset, PropertyInfo, ValueType};
|
||||
|
||||
|
@ -83,7 +84,7 @@ impl From<u32> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
impl crate::abi::properties::InterpolatedPropertyValue for Color {
|
||||
impl InterpolatedPropertyValue for Color {
|
||||
fn interpolate(self, target_value: Self, t: f32) -> Self {
|
||||
Self {
|
||||
red: self.red.interpolate(target_value.red, t),
|
||||
|
|
|
@ -28,7 +28,6 @@ pub mod abi {
|
|||
#![allow(unsafe_code)]
|
||||
pub mod datastructures;
|
||||
pub mod model;
|
||||
pub mod properties;
|
||||
pub mod sharedarray;
|
||||
pub mod signals;
|
||||
pub mod slice;
|
||||
|
@ -37,6 +36,7 @@ pub mod abi {
|
|||
}
|
||||
|
||||
pub mod items;
|
||||
pub mod properties;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use abi::string::SharedString;
|
||||
|
@ -48,7 +48,7 @@ pub use abi::sharedarray::SharedArray;
|
|||
pub use graphics::Resource;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use abi::properties::Property;
|
||||
pub use properties::Property;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use abi::signals::Signal;
|
||||
|
@ -77,4 +77,5 @@ pub fn use_modules() -> usize {
|
|||
+ layout::solve_grid_layout as usize
|
||||
+ item_tree::ffi::sixtyfps_visit_item_tree as usize
|
||||
+ graphics::ffi::sixtyfps_new_path_elements as usize
|
||||
+ properties::ffi::sixtyfps_property_init as usize
|
||||
}
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
thin dst container, and intrusive linked list
|
||||
*/
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
mod single_linked_list_pin {
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
///! A singled linked list whose nodes are pinned
|
||||
use core::pin::Pin;
|
||||
type NodePtr<T> = Option<Pin<Box<SingleLinkedListPinNode<T>>>>;
|
||||
|
@ -726,85 +730,6 @@ fn properties_simple_test() {
|
|||
assert_eq!(g(&compo.area), 8 * 8 * 2);
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_void = ();
|
||||
#[repr(C)]
|
||||
/// Has the same layout as PropertyHandle
|
||||
pub struct PropertyHandleOpaque(PropertyHandle);
|
||||
|
||||
/// Initialize the first pointer of the Property. Does not initialize the content.
|
||||
/// `out` is assumed to be uninitialized
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_init(out: *mut PropertyHandleOpaque) {
|
||||
core::ptr::write(out, PropertyHandleOpaque(PropertyHandle::default()));
|
||||
}
|
||||
|
||||
/// To be called before accessing the value
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_update(handle: &PropertyHandleOpaque, val: *mut c_void) {
|
||||
handle.0.update(val);
|
||||
handle.0.register_as_dependency_to_current_binding();
|
||||
}
|
||||
|
||||
/// Mark the fact that the property was changed and that its binding need to be removed, and
|
||||
/// The dependencies marked dirty
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_changed(handle: &PropertyHandleOpaque) {
|
||||
handle.0.remove_binding();
|
||||
handle.0.mark_dirty();
|
||||
}
|
||||
|
||||
fn make_c_function_binding(
|
||||
binding: extern "C" fn(*mut c_void, *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> impl Fn(*mut ()) -> BindingResult {
|
||||
struct CFunctionBinding<T> {
|
||||
binding_function: extern "C" fn(*mut c_void, *mut T),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
}
|
||||
|
||||
impl<T> Drop for CFunctionBinding<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(x) = self.drop_user_data {
|
||||
x(self.user_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let b = CFunctionBinding { binding_function: binding, user_data, drop_user_data };
|
||||
|
||||
move |value_ptr| {
|
||||
(b.binding_function)(b.user_data, value_ptr);
|
||||
BindingResult::KeepBinding
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a binding
|
||||
///
|
||||
/// The current implementation will do usually two memory alocation:
|
||||
/// 1. the allocation from the calling code to allocate user_data
|
||||
/// 2. the box allocation within this binding
|
||||
/// It might be possible to reduce that by passing something with a
|
||||
/// vtable, so there is the need for less memory allocation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_binding(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(user_data: *mut c_void, pointer_to_value: *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
let binding = make_c_function_binding(binding, user_data, drop_user_data);
|
||||
handle.0.set_binding(binding);
|
||||
}
|
||||
|
||||
/// Destroy handle
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_drop(handle: *mut PropertyHandleOpaque) {
|
||||
core::ptr::read(handle);
|
||||
}
|
||||
|
||||
/// InterpolatedPropertyValue is a trait used to enable properties to be used with
|
||||
/// animations that interpolate values. The basic requirement is the ability to apply
|
||||
/// a progress that's typically between 0 and 1 to a range.
|
||||
|
@ -841,126 +766,6 @@ impl InterpolatedPropertyValue for u8 {
|
|||
}
|
||||
}
|
||||
|
||||
fn c_set_animated_value<T: InterpolatedPropertyValue>(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: T,
|
||||
to: T,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
let d = RefCell::new(PropertyValueAnimationData::new(from, to, animation_data.clone()));
|
||||
handle.0.set_binding(move |val: *mut ()| {
|
||||
let (value, finished) = d.borrow_mut().compute_interpolated_value();
|
||||
unsafe {
|
||||
*(val as *mut T) = value;
|
||||
}
|
||||
if finished {
|
||||
BindingResult::RemoveBinding
|
||||
} else {
|
||||
crate::animations::CURRENT_ANIMATION_DRIVER
|
||||
.with(|driver| driver.set_has_active_animations());
|
||||
BindingResult::KeepBinding
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for an integer property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_int(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: i32,
|
||||
to: i32,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data)
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for a float property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_float(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: f32,
|
||||
to: f32,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data)
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for a color property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_color(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: Color,
|
||||
to: Color,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data);
|
||||
}
|
||||
|
||||
unsafe fn c_set_animated_binding<T: InterpolatedPropertyValue>(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut T),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
let binding = core::mem::transmute::<
|
||||
extern "C" fn(*mut c_void, *mut T),
|
||||
extern "C" fn(*mut c_void, *mut ()),
|
||||
>(binding);
|
||||
handle.0.set_binding(AnimatedBindingCallable::<T> {
|
||||
original_binding: PropertyHandle {
|
||||
handle: Cell::new(
|
||||
(alloc_binding_holder(make_c_function_binding(binding, user_data, drop_user_data))
|
||||
as usize)
|
||||
| 0b10,
|
||||
),
|
||||
},
|
||||
state: Cell::new(AnimatedBindingState::NotAnimating),
|
||||
animation_data: RefCell::new(PropertyValueAnimationData::new(
|
||||
T::default(),
|
||||
T::default(),
|
||||
animation_data.clone(),
|
||||
)),
|
||||
});
|
||||
handle.0.mark_dirty();
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for an integer property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_int(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut i32),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for a float property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_float(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut f32),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for a color property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_color(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut Color),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod animation_tests {
|
||||
use super::*;
|
||||
|
@ -1221,48 +1026,260 @@ fn test_property_listener_scope() {
|
|||
assert!(!scope.is_dirty());
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Opaque type representing the PropertyListenerScope
|
||||
pub struct PropertyListenerOpaque {
|
||||
dependencies: usize,
|
||||
dep_nodes: [usize; 2],
|
||||
vtable: usize,
|
||||
dirty: bool,
|
||||
}
|
||||
pub(crate) mod ffi {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_eq_align!(PropertyListenerOpaque, PropertyListenerScope);
|
||||
static_assertions::assert_eq_size!(PropertyListenerOpaque, PropertyListenerScope);
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_void = ();
|
||||
#[repr(C)]
|
||||
/// Has the same layout as PropertyHandle
|
||||
pub struct PropertyHandleOpaque(PropertyHandle);
|
||||
|
||||
/// Initialize the first pointer of the PropertyListenerScope.
|
||||
/// `out` is assumed to be uninitialized
|
||||
/// sixtyfps_property_listener_scope_drop need to be called after that
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_init(out: *mut PropertyListenerOpaque) {
|
||||
core::ptr::write(out as *mut PropertyListenerScope, PropertyListenerScope::default());
|
||||
}
|
||||
/// Initialize the first pointer of the Property. Does not initialize the content.
|
||||
/// `out` is assumed to be uninitialized
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_init(out: *mut PropertyHandleOpaque) {
|
||||
core::ptr::write(out, PropertyHandleOpaque(PropertyHandle::default()));
|
||||
}
|
||||
|
||||
/// Call the callback with the user data. Any properties access within the callback will be registered.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_evaluate(
|
||||
handle: *const PropertyListenerOpaque,
|
||||
callback: extern "C" fn(user_data: *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
) {
|
||||
Pin::new_unchecked(&*(handle as *const PropertyListenerScope)).evaluate(|| callback(user_data))
|
||||
}
|
||||
/// To be called before accessing the value
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_update(
|
||||
handle: &PropertyHandleOpaque,
|
||||
val: *mut c_void,
|
||||
) {
|
||||
handle.0.update(val);
|
||||
handle.0.register_as_dependency_to_current_binding();
|
||||
}
|
||||
|
||||
/// Query if the property listener is dirty
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_is_dirty(
|
||||
handle: *const PropertyListenerOpaque,
|
||||
) -> bool {
|
||||
(*(handle as *const PropertyListenerScope)).is_dirty()
|
||||
}
|
||||
/// Mark the fact that the property was changed and that its binding need to be removed, and
|
||||
/// The dependencies marked dirty
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_changed(handle: &PropertyHandleOpaque) {
|
||||
handle.0.remove_binding();
|
||||
handle.0.mark_dirty();
|
||||
}
|
||||
|
||||
/// Destroy handle
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_drop(
|
||||
handle: *mut PropertyListenerOpaque,
|
||||
) {
|
||||
core::ptr::read(handle as *mut PropertyListenerScope);
|
||||
fn make_c_function_binding(
|
||||
binding: extern "C" fn(*mut c_void, *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> impl Fn(*mut ()) -> BindingResult {
|
||||
struct CFunctionBinding<T> {
|
||||
binding_function: extern "C" fn(*mut c_void, *mut T),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
}
|
||||
|
||||
impl<T> Drop for CFunctionBinding<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(x) = self.drop_user_data {
|
||||
x(self.user_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let b = CFunctionBinding { binding_function: binding, user_data, drop_user_data };
|
||||
|
||||
move |value_ptr| {
|
||||
(b.binding_function)(b.user_data, value_ptr);
|
||||
BindingResult::KeepBinding
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a binding
|
||||
///
|
||||
/// The current implementation will do usually two memory alocation:
|
||||
/// 1. the allocation from the calling code to allocate user_data
|
||||
/// 2. the box allocation within this binding
|
||||
/// It might be possible to reduce that by passing something with a
|
||||
/// vtable, so there is the need for less memory allocation.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_binding(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(user_data: *mut c_void, pointer_to_value: *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) {
|
||||
let binding = make_c_function_binding(binding, user_data, drop_user_data);
|
||||
handle.0.set_binding(binding);
|
||||
}
|
||||
|
||||
/// Destroy handle
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_drop(handle: *mut PropertyHandleOpaque) {
|
||||
core::ptr::read(handle);
|
||||
}
|
||||
|
||||
fn c_set_animated_value<T: InterpolatedPropertyValue>(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: T,
|
||||
to: T,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
let d = RefCell::new(PropertyValueAnimationData::new(from, to, animation_data.clone()));
|
||||
handle.0.set_binding(move |val: *mut ()| {
|
||||
let (value, finished) = d.borrow_mut().compute_interpolated_value();
|
||||
unsafe {
|
||||
*(val as *mut T) = value;
|
||||
}
|
||||
if finished {
|
||||
BindingResult::RemoveBinding
|
||||
} else {
|
||||
crate::animations::CURRENT_ANIMATION_DRIVER
|
||||
.with(|driver| driver.set_has_active_animations());
|
||||
BindingResult::KeepBinding
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for an integer property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_int(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: i32,
|
||||
to: i32,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data)
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for a float property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_float(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: f32,
|
||||
to: f32,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data)
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation to the specified target value for a color property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_value_color(
|
||||
handle: &PropertyHandleOpaque,
|
||||
from: Color,
|
||||
to: Color,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_value(handle, from, to, animation_data);
|
||||
}
|
||||
|
||||
unsafe fn c_set_animated_binding<T: InterpolatedPropertyValue>(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut T),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
let binding = core::mem::transmute::<
|
||||
extern "C" fn(*mut c_void, *mut T),
|
||||
extern "C" fn(*mut c_void, *mut ()),
|
||||
>(binding);
|
||||
handle.0.set_binding(AnimatedBindingCallable::<T> {
|
||||
original_binding: PropertyHandle {
|
||||
handle: Cell::new(
|
||||
(alloc_binding_holder(make_c_function_binding(
|
||||
binding,
|
||||
user_data,
|
||||
drop_user_data,
|
||||
)) as usize)
|
||||
| 0b10,
|
||||
),
|
||||
},
|
||||
state: Cell::new(AnimatedBindingState::NotAnimating),
|
||||
animation_data: RefCell::new(PropertyValueAnimationData::new(
|
||||
T::default(),
|
||||
T::default(),
|
||||
animation_data.clone(),
|
||||
)),
|
||||
});
|
||||
handle.0.mark_dirty();
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for an integer property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_int(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut i32),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for a float property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_float(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut f32),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
/// Internal function to set up a property animation between values produced by the specified binding for a color property.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_set_animated_binding_color(
|
||||
handle: &PropertyHandleOpaque,
|
||||
binding: extern "C" fn(*mut c_void, *mut Color),
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
animation_data: &PropertyAnimation,
|
||||
) {
|
||||
c_set_animated_binding(handle, binding, user_data, drop_user_data, animation_data);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Opaque type representing the PropertyListenerScope
|
||||
pub struct PropertyListenerOpaque {
|
||||
dependencies: usize,
|
||||
dep_nodes: [usize; 2],
|
||||
vtable: usize,
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
static_assertions::assert_eq_align!(PropertyListenerOpaque, PropertyListenerScope);
|
||||
static_assertions::assert_eq_size!(PropertyListenerOpaque, PropertyListenerScope);
|
||||
|
||||
/// Initialize the first pointer of the PropertyListenerScope.
|
||||
/// `out` is assumed to be uninitialized
|
||||
/// sixtyfps_property_listener_scope_drop need to be called after that
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_init(
|
||||
out: *mut PropertyListenerOpaque,
|
||||
) {
|
||||
core::ptr::write(out as *mut PropertyListenerScope, PropertyListenerScope::default());
|
||||
}
|
||||
|
||||
/// Call the callback with the user data. Any properties access within the callback will be registered.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_evaluate(
|
||||
handle: *const PropertyListenerOpaque,
|
||||
callback: extern "C" fn(user_data: *mut c_void),
|
||||
user_data: *mut c_void,
|
||||
) {
|
||||
Pin::new_unchecked(&*(handle as *const PropertyListenerScope))
|
||||
.evaluate(|| callback(user_data))
|
||||
}
|
||||
|
||||
/// Query if the property listener is dirty
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_is_dirty(
|
||||
handle: *const PropertyListenerOpaque,
|
||||
) -> bool {
|
||||
(*(handle as *const PropertyListenerScope)).is_dirty()
|
||||
}
|
||||
|
||||
/// Destroy handle
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sixtyfps_property_listener_scope_drop(
|
||||
handle: *mut PropertyListenerOpaque,
|
||||
) {
|
||||
core::ptr::read(handle as *mut PropertyListenerScope);
|
||||
}
|
||||
}
|
|
@ -109,7 +109,7 @@ impl<Item, T: Clone, Value: 'static> PropertyInfo<Item, Value>
|
|||
where
|
||||
Value: TryInto<T>,
|
||||
T: TryInto<Value>,
|
||||
T: crate::abi::properties::InterpolatedPropertyValue,
|
||||
T: crate::properties::InterpolatedPropertyValue,
|
||||
{
|
||||
fn get(&self, item: Pin<&Item>) -> Result<Value, ()> {
|
||||
self.0.get(item)
|
||||
|
|
|
@ -8,11 +8,12 @@ use sixtyfps_compilerlib::layout::{GridLayout, Layout, LayoutItem, PathLayout};
|
|||
use sixtyfps_compilerlib::typeregister::Type;
|
||||
use sixtyfps_compilerlib::*;
|
||||
use sixtyfps_corelib::abi::datastructures::{ComponentVTable, ItemVTable, WindowProperties};
|
||||
use sixtyfps_corelib::abi::{properties::PropertyListenerScope, slice::Slice};
|
||||
use sixtyfps_corelib::abi::slice::Slice;
|
||||
use sixtyfps_corelib::graphics::Resource;
|
||||
use sixtyfps_corelib::item_tree::{ItemTreeNode, ItemVisitorRefMut};
|
||||
use sixtyfps_corelib::items::{Flickable, PropertyAnimation, Rectangle};
|
||||
use sixtyfps_corelib::layout::LayoutInfo;
|
||||
use sixtyfps_corelib::properties::{InterpolatedPropertyValue, PropertyListenerScope};
|
||||
use sixtyfps_corelib::rtti::PropertyInfo;
|
||||
use sixtyfps_corelib::ComponentRefPin;
|
||||
use sixtyfps_corelib::{rtti, Color, Property, SharedString, Signal};
|
||||
|
@ -324,9 +325,8 @@ fn generate_component(root_component: &Rc<object_tree::Component>) -> Rc<Compone
|
|||
dynamic_type::StaticTypeInfo::new::<Property<T>>(),
|
||||
)
|
||||
}
|
||||
fn animated_property_info<
|
||||
T: Clone + Default + sixtyfps_corelib::abi::properties::InterpolatedPropertyValue + 'static,
|
||||
>() -> (Box<dyn PropertyInfo<u8, eval::Value>>, dynamic_type::StaticTypeInfo)
|
||||
fn animated_property_info<T: Clone + Default + InterpolatedPropertyValue + 'static>(
|
||||
) -> (Box<dyn PropertyInfo<u8, eval::Value>>, dynamic_type::StaticTypeInfo)
|
||||
where
|
||||
T: std::convert::TryInto<eval::Value>,
|
||||
eval::Value: std::convert::TryInto<T>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue