use alloc::boxed::Box;
use nami::Signal;
use waterui::drag_drop::{DragData, Draggable, DropDestination};
use waterui_str::Str;
use crate::bridge::closure::RetainedCallback;
use crate::{IntoFFI, WuiEnv, WuiStr};
use core::ptr;
#[repr(C)]
#[derive(Debug)]
pub enum WuiDragDataTag {
Text = 0,
Url = 1,
}
#[repr(C)]
#[derive(Debug)]
pub struct WuiDragData {
pub tag: WuiDragDataTag,
pub value: WuiStr,
}
impl IntoFFI for DragData {
type FFI = WuiDragData;
fn into_ffi(self) -> Self::FFI {
match self {
Self::Text(s) => WuiDragData {
tag: WuiDragDataTag::Text,
value: s.into_ffi(),
},
Self::Url(s) => WuiDragData {
tag: WuiDragDataTag::Url,
value: s.into_ffi(),
},
_ => panic!("waterui drag/drop FFI does not support this DragData variant"),
}
}
}
#[derive(Debug)]
pub struct WuiDraggableWrapper(pub Draggable);
#[repr(C)]
#[derive(Debug)]
pub struct WuiDraggable {
pub inner: *mut WuiDraggableWrapper,
}
impl IntoFFI for Draggable {
type FFI = WuiDraggable;
fn into_ffi(self) -> Self::FFI {
WuiDraggable {
inner: Box::into_raw(Box::new(WuiDraggableWrapper(self))),
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_draggable_get_data(draggable: *const WuiDraggable) -> WuiDragData {
unsafe {
let draggable = crate::borrow_ffi(draggable);
let wrapper = crate::borrow_ffi(draggable.inner);
wrapper.0.data.get().into_ffi()
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_drop_draggable(draggable: *mut WuiDraggable) {
unsafe {
let draggable = crate::borrow_ffi_mut(draggable);
let inner = draggable.inner;
drop(Box::from_raw(inner));
draggable.inner = ptr::null_mut();
}
}
#[derive(Debug)]
pub struct WuiDropHandler(pub RetainedCallback<DropDestination>);
#[repr(C)]
#[derive(Debug)]
pub struct WuiDropDestination {
pub handler: *mut WuiDropHandler,
}
impl IntoFFI for DropDestination {
type FFI = WuiDropDestination;
fn into_ffi(self) -> Self::FFI {
WuiDropDestination {
handler: Box::into_raw(Box::new(WuiDropHandler(RetainedCallback::new(self)))),
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_call_drop_handler(
dest: *const WuiDropDestination,
env: *const WuiEnv,
data_tag: WuiDragDataTag,
data_value: *const core::ffi::c_char,
) {
unsafe {
let dest = crate::borrow_ffi(dest);
let handler = crate::borrow_ffi(dest.handler).0.clone();
let env = crate::borrow_ffi(env).0.clone();
let data_value = crate::borrow_ffi(data_value);
let c_str = core::ffi::CStr::from_ptr(data_value);
let value = Str::from(core::str::from_utf8_unchecked(c_str.to_bytes()).to_owned());
let data = match data_tag {
WuiDragDataTag::Text => DragData::Text(value),
WuiDragDataTag::Url => DragData::Url(value),
};
let mut env_with_data = env;
env_with_data.insert(data);
handler.call(|handler| (handler.on_drop)(&env_with_data));
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_call_drop_enter_handler(
dest: *const WuiDropDestination,
env: *const WuiEnv,
) {
unsafe {
let dest = crate::borrow_ffi(dest);
let handler = crate::borrow_ffi(dest.handler).0.clone();
let env = crate::borrow_ffi(env).0.clone();
handler.call(|handler| {
if let Some(on_enter) = &mut handler.on_enter {
on_enter(&env);
}
});
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_call_drop_exit_handler(
dest: *const WuiDropDestination,
env: *const WuiEnv,
) {
unsafe {
let dest = crate::borrow_ffi(dest);
let handler = crate::borrow_ffi(dest.handler).0.clone();
let env = crate::borrow_ffi(env).0.clone();
handler.call(|handler| {
if let Some(on_exit) = &mut handler.on_exit {
on_exit(&env);
}
});
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_drop_drop_destination(dest: *mut WuiDropDestination) {
unsafe {
let dest = crate::borrow_ffi_mut(dest);
let handler = dest.handler;
drop(Box::from_raw(handler));
dest.handler = ptr::null_mut();
}
}