use super::*;
use crate::abi;
use crate::resolve;
use core::ffi::c_void;
use crate::mangle;
mangle::modifier_types! {
pub(crate) TRANSITION_T = ty("_TraitWritingModifier").of(vec![ty("TransitionTraitKey")]);
pub(crate) ON_APPEAR_T = ty("_AppearanceActionModifier");
pub(crate) ANIMATION_T = ty("_AnimationModifier").of(vec![Type::Verbatim("Si".into())]);
}
pub(crate) unsafe fn opaque_modifier_for_transition(
view: &ViewHandle,
boxed: u64,
) -> ViewHandle {
unsafe {
let (_, _, size) = TRANSITION_T.applied_to(view.meta);
let r = abi::call_modifier(
resolve::transition_fn(),
view.value_ptr(),
view.meta,
view.wt,
&[boxed],
[0.0; 4],
size,
);
wrap_modified(r, &TRANSITION_T, view)
}
}
pub fn transition_opacity(view: &ViewHandle) -> ViewHandle {
unsafe {
let meta = abi::metadata0(resolve::any_transition_ma());
let (value, _) = static_getter(resolve::transition_opacity(), meta);
let (_, _, size) = TRANSITION_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::transition_fn(), view.value_ptr(), view.meta, view.wt, &[value], [0.0; 4], size);
wrap_modified(r, &TRANSITION_T, view)
}
}
pub fn transition_slide(view: &ViewHandle) -> ViewHandle {
unsafe {
let meta = abi::metadata0(resolve::any_transition_ma());
let (value, _) = static_getter(resolve::transition_slide(), meta);
let (_, _, size) = TRANSITION_T.applied_to(view.meta);
let r = abi::call_modifier(
resolve::transition_fn(),
view.value_ptr(),
view.meta,
view.wt,
&[value],
[0.0; 4],
size,
);
wrap_modified(r, &TRANSITION_T, view)
}
}
swift_statics! {
pub enum AnimationKind {
Default = c"$s7SwiftUI9AnimationV7defaultACvgZ",
EaseIn = c"$s7SwiftUI9AnimationV6easeInACvgZ",
EaseInOut = c"$s7SwiftUI9AnimationV9easeInOutACvgZ",
EaseOut = c"$s7SwiftUI9AnimationV7easeOutACvgZ",
Linear = c"$s7SwiftUI9AnimationV6linearACvgZ",
}
}
pub(crate) unsafe fn animation_word(view: &ViewHandle, anim: u64, value: i64) -> ViewHandle {
unsafe {
let int_meta = resolve::int_meta();
let eq_wt = abi::get_view_wt_for_proto(int_meta, resolve::equatable_proto());
assert!(!eq_wt.is_null(), "Int: Equatable");
let (_, _, size) = ANIMATION_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let this = view.value_ptr();
let mut v = value;
core::arch::asm!("blr {f}", f = in(reg) resolve::animation_fn(),
in("x0") anim,
in("x1") &mut v as *mut i64,
in("x2") view.meta,
in("x3") int_meta,
in("x4") view.wt,
in("x5") eq_wt,
in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_modified(result, &ANIMATION_T, view)
}
}
pub fn animation(view: &ViewHandle, value: i64) -> ViewHandle {
animation_kind(view, AnimationKind::Default, value)
}
pub fn animation_kind(view: &ViewHandle, kind: AnimationKind, value: i64) -> ViewHandle {
unsafe {
let anim_meta = abi::metadata0(resolve::animation_ma());
let (anim, _) = static_getter(kind.resolved(), anim_meta);
let int_meta = resolve::int_meta();
let eq_wt = abi::get_view_wt_for_proto(int_meta, resolve::equatable_proto());
assert!(!eq_wt.is_null(), "Int: Equatable");
let (_, _, size) = ANIMATION_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let this = view.value_ptr();
let mut v = value;
core::arch::asm!("blr {f}", f = in(reg) resolve::animation_fn(),
in("x0") anim,
in("x1") &mut v as *mut i64,
in("x2") view.meta,
in("x3") int_meta,
in("x4") view.wt,
in("x5") eq_wt,
in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_modified(result, &ANIMATION_T, view)
}
}
pub fn on_appear(view: &ViewHandle, action: impl Fn() + 'static) -> ViewHandle {
unsafe {
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
invoke_action,
boxed_ctx(Box::new(action) as Box<dyn Fn()>),
))) as *mut abi::ClosureCtx;
let (_, _, size) = ON_APPEAR_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::on_appear_fn(), view.value_ptr(), view.meta, view.wt,
&[abi::swift_closure_thunk as *const () as u64, ctx as u64],
[0.0; 4],
size,
);
wrap_modified(r, &ON_APPEAR_T, view)
}
}
pub fn on_tap_gesture(view: &ViewHandle, count: i64, action: impl Fn() + 'static) -> ViewHandle {
unsafe {
let boxed: Box<dyn Fn()> = Box::new(action);
let payload = Box::into_raw(Box::new(boxed)) as *mut c_void;
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
super::run_boxed_action,
payload,
))) as *mut abi::ClosureCtx;
let subst = [view.meta, view.wt];
let (meta, wt, size) = opaque_result_type(resolve::on_tap_oret(), &subst);
let r = abi::call_modifier(resolve::on_tap_fn(), view.value_ptr(), view.meta, view.wt,
&[count as u64, abi::swift_closure_thunk as *const () as u64, ctx as u64],
[0.0; 4],
size,
);
wrap_owned(r, meta, wt)
}
}
pub fn on_long_press_gesture(
view: &ViewHandle,
duration: f64,
max_distance: f64,
action: impl Fn() + 'static,
) -> ViewHandle {
unsafe {
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
invoke_action,
boxed_ctx(Box::new(action) as Box<dyn Fn()>),
))) as *mut abi::ClosureCtx;
let subst = [view.meta, view.wt];
let (meta, wt, size) = opaque_result_type(resolve::on_long_press_oret(), &subst);
let r = abi::call_modifier(resolve::on_long_press_fn(), view.value_ptr(), view.meta, view.wt,
&[0, 0, abi::swift_closure_thunk as *const () as u64, ctx as u64],
[duration, max_distance, 0.0, 0.0],
size,
);
wrap_owned(r, meta, wt)
}
}
pub fn context_menu(view: &ViewHandle, items: &ViewHandle) -> ViewHandle {
unsafe {
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(items, Content::Concrete),
))) as *mut abi::ClosureCtx;
let subst = [
view.meta,
items.meta,
view.wt,
items.wt,
];
let (meta, wt, size) = opaque_result_type(resolve::context_menu_oret(), &subst);
let mut result = vec![0u8; size];
let this = view.value_ptr();
core::arch::asm!("blr {f}", f = in(reg) resolve::context_menu_fn(),
in("x0") abi::swift_closure_thunk as *const c_void,
in("x1") ctx,
in("x2") view.meta, in("x3") items.meta, in("x4") view.wt, in("x5") items.wt, in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_owned(result, meta, wt)
}
}
pub fn transition_scale(scale: f64, anchor: (f64, f64)) -> u64 {
unsafe {
let out: u64;
core::arch::asm!("blr {f}", f = in(reg) resolve::transition_scale_anchor(),
in("d0") scale, in("d1") anchor.0, in("d2") anchor.1,
lateout("x0") out,
lateout("x20") _,
lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
out
}
}
pub fn transition_opacity_value() -> u64 {
unsafe {
let meta = abi::metadata0(resolve::any_transition_ma());
static_getter(resolve::transition_opacity(), meta).0
}
}
pub fn transition_identity_value() -> u64 {
unsafe {
let meta = abi::metadata0(resolve::any_transition_ma());
static_getter(resolve::transition_identity(), meta).0
}
}
pub fn transition_scale_value() -> u64 {
unsafe {
let meta = abi::metadata0(resolve::any_transition_ma());
static_getter(resolve::transition_scale(), meta).0
}
}
pub fn transition_combined(lhs: u64, rhs: u64) -> u64 {
unsafe {
let out: u64;
core::arch::asm!("blr {f}", f = in(reg) resolve::transition_combined(),
in("x0") rhs,
in("x1") lhs,
lateout("x0") out,
lateout("x20") _,
lateout("x2") _, lateout("x3") _, lateout("x4") _,
lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
out
}
}
pub fn transition(view: &ViewHandle, value: u64) -> ViewHandle {
unsafe {
let (_, _, size) = TRANSITION_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::transition_fn(), view.value_ptr(), view.meta, view.wt, &[value], [0.0; 4], size);
wrap_modified(r, &TRANSITION_T, view)
}
}
pub fn context_menu_preview(
view: &ViewHandle,
items: &ViewHandle,
preview: &ViewHandle,
) -> ViewHandle {
unsafe {
let items_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(items, Content::Concrete),
))) as *mut abi::ClosureCtx;
let preview_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(preview, Content::Concrete),
))) as *mut abi::ClosureCtx;
let subst = [view.meta, items.meta, preview.meta, view.wt, items.wt, preview.wt];
let (meta, wt, size) = opaque_result_type(resolve::context_menu_preview_oret(), &subst);
let mut result = vec![0u8; size];
let this = view.value_ptr();
core::arch::asm!(
"sub sp, sp, #16",
"stp {mw}, {pw}, [sp]",
"blr {f}",
"add sp, sp, #16",
f = in(reg) resolve::context_menu_preview_fn(),
mw = in(reg) items.wt,
pw = in(reg) preview.wt,
in("x0") abi::swift_closure_thunk as *const c_void,
in("x1") items_ctx,
in("x2") abi::swift_closure_thunk as *const c_void,
in("x3") preview_ctx,
in("x4") view.meta,
in("x5") items.meta,
in("x6") preview.meta,
in("x7") view.wt,
in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_owned(result, meta, wt)
}
}