#[macro_export]
macro_rules! panel_event {
(
$handler_name:ident {
$(
$method:ident ( $first_param:ident : $first_type:ty $(, $param:ident : $param_type:ty)* $(,)? ) -> $return_type:ty
),* $(,)?
}
) => {
$crate::pastey::paste! {
$(
pub type [<$handler_name $method:camel Callback>] = std::boxed::Box<
dyn Fn($first_type $(, $param_type)*) -> $return_type
>;
)*
struct [<$handler_name Ivars>] {
$(
[<$method:snake>]: std::cell::Cell<Option<[<$handler_name $method:camel Callback>]>>,
)*
mouse_entered_callback: std::cell::Cell<Option<Box<dyn Fn(&$crate::objc2_app_kit::NSEvent)>>>,
mouse_exited_callback: std::cell::Cell<Option<Box<dyn Fn(&$crate::objc2_app_kit::NSEvent)>>>,
mouse_moved_callback: std::cell::Cell<Option<Box<dyn Fn(&$crate::objc2_app_kit::NSEvent)>>>,
cursor_update_callback: std::cell::Cell<Option<Box<dyn Fn(&$crate::objc2_app_kit::NSEvent)>>>,
}
define_class!(
#[unsafe(super(NSObject))]
#[name = stringify!($handler_name)]
#[thread_kind = MainThreadOnly]
#[ivars = [<$handler_name Ivars>]]
struct $handler_name;
unsafe impl NSObjectProtocol for $handler_name {}
unsafe impl NSWindowDelegate for $handler_name {
$(
#[doc = concat!(" Objective-C delegate method: ", stringify!($method), "_:", $(stringify!([<$param:lower_camel>]), ":"),*)]
#[allow(non_snake_case)]
#[unsafe(method([<$method:lower_camel>]:$([<$param:lower_camel>]:)*))]
fn [<__ $method:snake>](&self, [<$first_param:lower_camel>]: $first_type $(, [<$param:lower_camel>]: $param_type )* ) -> $return_type {
let callback = self.ivars().[<$method:snake>].take();
if let Some(callback) = callback {
let result = callback([<$first_param:lower_camel>] $(, [<$param:lower_camel>])*);
self.ivars().[<$method:snake>].set(Some(callback));
result
} else {
Default::default()
}
}
)*
}
impl $handler_name {
#[unsafe(method(mouseEntered:))]
fn mouse_entered(&self, event: &$crate::objc2_app_kit::NSEvent) {
let ivars = self.ivars();
if let Some(callback) = ivars.mouse_entered_callback.take() {
callback(event);
ivars.mouse_entered_callback.set(Some(callback));
}
}
#[unsafe(method(mouseExited:))]
fn mouse_exited(&self, event: &$crate::objc2_app_kit::NSEvent) {
let ivars = self.ivars();
if let Some(callback) = ivars.mouse_exited_callback.take() {
callback(event);
ivars.mouse_exited_callback.set(Some(callback));
}
}
#[unsafe(method(mouseMoved:))]
fn mouse_moved(&self, event: &$crate::objc2_app_kit::NSEvent) {
let ivars = self.ivars();
if let Some(callback) = ivars.mouse_moved_callback.take() {
callback(event);
ivars.mouse_moved_callback.set(Some(callback));
}
}
#[unsafe(method(cursorUpdate:))]
fn cursor_update(&self, event: &$crate::objc2_app_kit::NSEvent) {
let ivars = self.ivars();
if let Some(callback) = ivars.cursor_update_callback.take() {
callback(event);
ivars.cursor_update_callback.set(Some(callback));
}
}
}
);
impl $handler_name {
pub fn new() -> Retained<Self> {
unsafe {
let mtm = MainThreadMarker::new().expect("Must be on main thread");
let this = Self::alloc(mtm);
let this = this.set_ivars([<$handler_name Ivars>] {
$(
[<$method:snake>]: std::cell::Cell::new(None),
)*
mouse_entered_callback: std::cell::Cell::new(None),
mouse_exited_callback: std::cell::Cell::new(None),
mouse_moved_callback: std::cell::Cell::new(None),
cursor_update_callback: std::cell::Cell::new(None),
});
msg_send![super(this), init]
}
}
$(
#[doc = " A callback for the `" $method "` event"]
pub fn [<$method:snake>]<F>(&self, callback: F)
where
F: Fn($first_type $(, $param_type)*) -> $return_type + 'static
{
let boxed_callback: [<$handler_name $method:camel Callback>] = std::boxed::Box::new(callback);
self.ivars().[<$method:snake>].set(Some(boxed_callback));
}
)*
pub fn on_mouse_entered<F>(&self, callback: F)
where
F: Fn(&$crate::objc2_app_kit::NSEvent) + 'static
{
self.ivars().mouse_entered_callback.set(Some(Box::new(callback)));
}
pub fn on_mouse_exited<F>(&self, callback: F)
where
F: Fn(&$crate::objc2_app_kit::NSEvent) + 'static
{
self.ivars().mouse_exited_callback.set(Some(Box::new(callback)));
}
pub fn on_mouse_moved<F>(&self, callback: F)
where
F: Fn(&$crate::objc2_app_kit::NSEvent) + 'static
{
self.ivars().mouse_moved_callback.set(Some(Box::new(callback)));
}
pub fn on_cursor_update<F>(&self, callback: F)
where
F: Fn(&$crate::objc2_app_kit::NSEvent) + 'static
{
self.ivars().cursor_update_callback.set(Some(Box::new(callback)));
}
}
impl std::convert::AsRef<ProtocolObject<dyn NSWindowDelegate>> for $handler_name {
fn as_ref(&self) -> &ProtocolObject<dyn NSWindowDelegate> {
unsafe {
ProtocolObject::from_ref(self)
}
}
}
}
};
}