use std::{cell::RefCell, os::raw::c_void};
use ohos_arkui_sys::ArkUI_AnimateCompleteCallback;
use crate::AnimationFinishCallbackType;
struct FinishCallbackContext {
callback: Option<Box<dyn Fn()>>,
}
pub struct AnimationFinishContext {
callback_context: Box<RefCell<FinishCallbackContext>>,
raw: RefCell<ArkUI_AnimateCompleteCallback>,
}
impl AnimationFinishContext {
pub fn callback<T: Fn() + 'static>(&self, callback: T) {
self.callback_context.borrow_mut().callback = Some(Box::new(callback));
}
pub fn clear_callback(&self) {
self.callback_context.borrow_mut().callback = None;
}
pub fn callback_type(&self, callback_type: AnimationFinishCallbackType) {
self.raw.borrow_mut().type_ = callback_type.into();
}
}
impl Default for AnimationFinishContext {
fn default() -> Self {
let callback_context = Box::new(RefCell::new(FinishCallbackContext { callback: None }));
let user_data =
callback_context.as_ref() as *const RefCell<FinishCallbackContext> as *mut c_void;
let raw = RefCell::new(ArkUI_AnimateCompleteCallback {
callback: Some(finish_callback_trampoline),
userData: user_data,
type_: AnimationFinishCallbackType::Logically.into(),
});
Self {
callback_context,
raw,
}
}
}
impl AnimationFinishContext {
pub(crate) fn raw(&self) -> *mut ArkUI_AnimateCompleteCallback {
self.raw.as_ptr()
}
}
unsafe extern "C" fn finish_callback_trampoline(user_data: *mut c_void) {
if user_data.is_null() {
return;
}
let context = unsafe { &*(user_data as *const RefCell<FinishCallbackContext>) };
if let Some(callback) = context.borrow().callback.as_ref() {
callback();
}
}