use core::{ffi::c_void, marker::PhantomData, sync::atomic::AtomicI32};
use oxivgl_sys::*;
use crate::widgets::AsLvHandle;
pub struct AnimHandle {
var: *mut c_void,
exec_cb: lv_anim_exec_xcb_t,
}
impl core::fmt::Debug for AnimHandle {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("AnimHandle").finish_non_exhaustive()
}
}
impl AnimHandle {
pub fn pause_for(&self, ms: u32) {
let ptr = unsafe { lv_anim_get(self.var, self.exec_cb) };
if !ptr.is_null() {
unsafe { lv_anim_pause_for(ptr, ms) };
}
}
}
pub struct Anim<'w> {
pub(crate) inner: lv_anim_t,
_widget: PhantomData<&'w ()>,
has_bezier_user_data: bool,
}
impl<'w> core::fmt::Debug for Anim<'w> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Anim").finish_non_exhaustive()
}
}
impl<'w> Anim<'w> {
pub fn new() -> Self {
let mut inner = unsafe { core::mem::zeroed::<lv_anim_t>() };
unsafe { lv_anim_init(&mut inner) };
Self { inner, _widget: PhantomData, has_bezier_user_data: false }
}
pub fn set_var(&mut self, obj: &'w impl AsLvHandle) -> &mut Self {
unsafe { lv_anim_set_var(&mut self.inner, obj.lv_handle() as *mut c_void) };
self
}
pub fn set_values(&mut self, start: i32, end: i32) -> &mut Self {
unsafe { lv_anim_set_values(&mut self.inner, start, end) };
self
}
pub fn set_duration(&mut self, ms: u32) -> &mut Self {
unsafe { lv_anim_set_duration(&mut self.inner, ms) };
self
}
pub fn set_delay(&mut self, ms: u32) -> &mut Self {
unsafe { lv_anim_set_delay(&mut self.inner, ms) };
self
}
pub fn set_exec_cb(&mut self, cb: lv_anim_exec_xcb_t) -> &mut Self {
unsafe { lv_anim_set_exec_cb(&mut self.inner, cb) };
self
}
pub fn set_custom_exec_cb(&mut self, cb: lv_anim_custom_exec_cb_t) -> &mut Self {
unsafe { lv_anim_set_custom_exec_cb(&mut self.inner, cb) };
self
}
pub fn set_path_cb(&mut self, cb: lv_anim_path_cb_t) -> &mut Self {
unsafe { lv_anim_set_path_cb(&mut self.inner, cb) };
self
}
pub fn set_reverse_duration(&mut self, ms: u32) -> &mut Self {
unsafe { lv_anim_set_reverse_duration(&mut self.inner, ms) };
self
}
pub fn set_reverse_delay(&mut self, ms: u32) -> &mut Self {
unsafe { lv_anim_set_reverse_delay(&mut self.inner, ms) };
self
}
pub fn set_repeat_count(&mut self, cnt: u32) -> &mut Self {
unsafe { lv_anim_set_repeat_count(&mut self.inner, cnt) };
self
}
pub fn set_repeat_delay(&mut self, ms: u32) -> &mut Self {
unsafe { lv_anim_set_repeat_delay(&mut self.inner, ms) };
self
}
pub fn set_bezier3_path(
&mut self,
p1: &'static AtomicI32,
p2: &'static AtomicI32,
) -> &mut Self {
if self.has_bezier_user_data {
unsafe {
drop(alloc::boxed::Box::from_raw(
self.inner.user_data as *mut [*const AtomicI32; 2],
));
}
}
let pair = alloc::boxed::Box::into_raw(alloc::boxed::Box::new([
p1 as *const AtomicI32,
p2 as *const AtomicI32,
]));
self.inner.user_data = pair as *mut c_void;
self.has_bezier_user_data = true;
unsafe { lv_anim_set_path_cb(&mut self.inner, Some(bezier3_path_cb)) };
self
}
pub fn start(&self) -> AnimHandle {
assert!(
!self.inner.var.is_null(),
"Anim::start() called without set_var() — would pass null to exec callback"
);
let ptr = unsafe { lv_anim_start(&self.inner) };
assert!(!ptr.is_null(), "lv_anim_start returned NULL");
AnimHandle {
var: self.inner.var,
exec_cb: self.inner.exec_cb,
}
}
}
pub unsafe extern "C" fn anim_path_linear(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_linear(a) }
}
pub unsafe extern "C" fn anim_path_overshoot(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_overshoot(a) }
}
pub unsafe extern "C" fn anim_path_ease_in(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_ease_in(a) }
}
pub unsafe extern "C" fn anim_path_ease_out(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_ease_out(a) }
}
pub unsafe extern "C" fn anim_path_ease_in_out(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_ease_in_out(a) }
}
pub unsafe extern "C" fn anim_path_bounce(a: *const lv_anim_t) -> i32 {
unsafe { lv_anim_path_bounce(a) }
}
unsafe extern "C" fn bezier3_path_cb(a: *const lv_anim_t) -> i32 {
let a = unsafe { &*a };
let pair = a.user_data as *const [*const AtomicI32; 2];
let [p1_ptr, p2_ptr] = unsafe { &*pair };
let p1 = unsafe { &**p1_ptr }.load(core::sync::atomic::Ordering::Relaxed);
let p2 = unsafe { &**p2_ptr }.load(core::sync::atomic::Ordering::Relaxed);
let t = unsafe { lv_map(a.act_time, 0, a.duration, 0, 1024) };
let step = unsafe { lv_bezier3(t, 0, p1 as u32, p2 as i32, 1024) };
let new_value = (step as i64 * (a.end_value - a.start_value) as i64) >> 10;
new_value as i32 + a.start_value
}
pub const ANIM_REPEAT_INFINITE: u32 = LV_ANIM_REPEAT_INFINITE;
pub unsafe extern "C" fn anim_set_translate_x(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_style_translate_x(var as *mut lv_obj_t, v, 0) };
}
pub unsafe extern "C" fn anim_set_x(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_x(var as *mut lv_obj_t, v) };
}
pub unsafe extern "C" fn anim_set_y(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_y(var as *mut lv_obj_t, v) };
}
pub unsafe extern "C" fn anim_set_size(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_size(var as *mut lv_obj_t, v, v) };
}
pub unsafe extern "C" fn anim_set_width(a: *mut lv_anim_t, v: i32) {
unsafe { lv_obj_set_width((*a).var as *mut lv_obj_t, v) };
}
pub unsafe extern "C" fn anim_set_height(a: *mut lv_anim_t, v: i32) {
unsafe { lv_obj_set_height((*a).var as *mut lv_obj_t, v) };
}
pub unsafe extern "C" fn anim_set_pad_row(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_style_pad_row(var as *mut lv_obj_t, v, 0) };
}
pub unsafe extern "C" fn anim_set_pad_column(var: *mut c_void, v: i32) {
unsafe { lv_obj_set_style_pad_column(var as *mut lv_obj_t, v, 0) };
}
pub unsafe extern "C" fn anim_set_slider_value(a: *mut lv_anim_t, v: i32) {
unsafe { lv_slider_set_value((*a).var as *mut lv_obj_t, v, false) };
}
pub unsafe extern "C" fn anim_set_arc_value(var: *mut c_void, v: i32) {
unsafe { lv_arc_set_value(var as *mut lv_obj_t, v) };
}
pub unsafe extern "C" fn anim_set_bar_value(var: *mut c_void, v: i32) {
unsafe { lv_bar_set_value(var as *mut lv_obj_t, v, true) };
}
pub unsafe extern "C" fn anim_set_scale_rotation(var: *mut c_void, v: i32) {
unsafe { lv_scale_set_rotation(var as *mut lv_obj_t, v) };
}