#![allow(trivial_casts)]
use std::sync::Once;
use objc::{
class,
declare::ClassDecl,
runtime::{Class, Object, Sel},
sel, sel_impl,
};
use crate::objective_c_runtime::id;
use super::{NSApplicationTerminateReply, NSMenu, NSAPPLICATION_PTR};
pub trait PNSApplicationDelegate {
fn will_finish_launching(&mut self) {}
fn did_finish_launching(&mut self) {}
fn did_become_active(&mut self) {}
fn will_resign_active(&mut self) {}
fn will_continue_user_activity(&mut self, _activity_type: &str) -> bool {
false
}
fn will_terminate(&mut self) {}
fn will_become_active(&mut self) {}
fn did_resign_active(&mut self) {}
fn will_hide(&mut self) {}
fn did_hide(&mut self) {}
fn will_unhide(&mut self) {}
fn did_unhide(&mut self) {}
fn will_update(&mut self) {}
fn did_update(&mut self) {}
fn should_terminate(&mut self) -> NSApplicationTerminateReply {
NSApplicationTerminateReply::Now
}
fn should_terminate_after_last_window_closed(&mut self) -> bool {
false
}
fn should_handle_reopen(&mut self, _has_visible_windows: bool) -> bool {
true
}
fn dock_menu(&mut self) -> Option<NSMenu> {
None
}
}
fn app<T>(this: &mut Object) -> &mut T {
unsafe {
let app_ptr: usize = *this.get_ivar(NSAPPLICATION_PTR);
let app = app_ptr as *mut T;
&mut *app
}
}
extern "C" fn will_finish_launching<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_finish_launching();
}
extern "C" fn did_finish_launching<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_finish_launching();
}
extern "C" fn will_become_active<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_become_active();
}
extern "C" fn did_become_active<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_become_active();
}
extern "C" fn will_resign_active<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_resign_active();
}
extern "C" fn did_resign_active<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_resign_active();
}
extern "C" fn should_terminate<T: PNSApplicationDelegate>(
this: &mut Object,
_: Sel,
_: id,
) -> NSApplicationTerminateReply {
app::<T>(this).should_terminate()
}
extern "C" fn will_terminate<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_terminate();
}
extern "C" fn will_hide<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_hide();
}
extern "C" fn did_hide<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_hide();
}
extern "C" fn will_unhide<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_unhide();
}
extern "C" fn did_unhide<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_unhide();
}
extern "C" fn will_update<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).will_update();
}
extern "C" fn did_update<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) {
app::<T>(this).did_update();
}
extern "C" fn should_terminate_after_last_window_closed<T>(this: &mut Object, _: Sel, _: id) -> bool
where
T: PNSApplicationDelegate,
{
app::<T>(this).should_terminate_after_last_window_closed()
}
extern "C" fn should_handle_reopen<T: PNSApplicationDelegate>(
this: &mut Object,
_: Sel,
_: id,
has_visible_windows: bool,
) -> bool {
app::<T>(this).should_handle_reopen(has_visible_windows)
}
#[allow(improper_ctypes_definitions)]
extern "C" fn dock_menu<T: PNSApplicationDelegate>(this: &mut Object, _: Sel, _: id) -> NSMenu {
app::<T>(this).dock_menu().unwrap_or_default()
}
pub fn register_app_delegate_class<T: PNSApplicationDelegate + PNSApplicationDelegate>(
) -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSObject);
let mut decl = ClassDecl::new("RSTNSApplicationDelegate", superclass).unwrap();
decl.add_ivar::<usize>(NSAPPLICATION_PTR);
decl.add_method(
sel!(applicationWillFinishLaunching:),
will_finish_launching::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidFinishLaunching:),
did_finish_launching::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationWillBecomeActive:),
will_become_active::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidBecomeActive:),
did_become_active::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationWillResignActive:),
will_resign_active::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidResignActive:),
did_resign_active::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationShouldTerminate:),
should_terminate::<T>
as extern "C" fn(&mut Object, _, _) -> NSApplicationTerminateReply,
);
decl.add_method(
sel!(applicationWillTerminate:),
will_terminate::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationWillHide:),
will_hide::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidHide:),
did_hide::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationWillUnhide:),
will_unhide::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidUnhide:),
did_unhide::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationWillUpdate:),
will_update::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationDidUpdate:),
did_update::<T> as extern "C" fn(&mut Object, _, _),
);
decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen::<T> as extern "C" fn(&mut Object, _, _, bool) -> bool,
);
decl.add_method(
sel!(applicationDockMenu:),
dock_menu::<T> as extern "C" fn(&mut Object, _, _) -> NSMenu,
);
decl.add_method(
sel!(applicationShouldTerminateAfterLastWindowClosed:),
should_terminate_after_last_window_closed::<T>
as extern "C" fn(&mut Object, _, _) -> bool,
);
DELEGATE_CLASS = decl.register();
});
unsafe { DELEGATE_CLASS }
}