use std::sync::Once;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, msg_send, sel, sel_impl};
use crate::foundation::load_or_register_class;
use crate::view::{VIEW_DELEGATE_PTR, ViewDelegate};
use crate::utils::load;
extern "C" fn will_appear<T: ViewDelegate>(this: &mut Object, _: Sel) {
unsafe {
let _: () = msg_send![super(this, class!(NSViewController)), viewWillAppear];
}
let controller = load::<T>(this, VIEW_DELEGATE_PTR);
controller.will_appear(false);
}
extern "C" fn did_appear<T: ViewDelegate>(this: &mut Object, _: Sel) {
unsafe {
let _: () = msg_send![super(this, class!(NSViewController)), viewDidAppear];
}
let controller = load::<T>(this, VIEW_DELEGATE_PTR);
controller.did_appear(false);
}
extern "C" fn will_disappear<T: ViewDelegate>(this: &mut Object, _: Sel) {
unsafe {
let _: () = msg_send![super(this, class!(NSViewController)), viewWillDisappear];
}
let controller = load::<T>(this, VIEW_DELEGATE_PTR);
controller.will_disappear(false);
}
extern "C" fn did_disappear<T: ViewDelegate>(this: &mut Object, _: Sel) {
unsafe {
let _: () = msg_send![super(this, class!(NSViewController)), viewDidDisappear];
}
let controller = load::<T>(this, VIEW_DELEGATE_PTR);
controller.did_disappear(false);
}
pub(crate) fn register_view_controller_class<T: ViewDelegate + 'static>(instance: &T) -> *const Class {
load_or_register_class("NSViewController", instance.subclass_name(), |decl| unsafe {
decl.add_ivar::<usize>(VIEW_DELEGATE_PTR);
decl.add_method(sel!(viewWillAppear), will_appear::<T> as extern "C" fn(&mut Object, _));
decl.add_method(sel!(viewDidAppear), did_appear::<T> as extern "C" fn(&mut Object, _));
decl.add_method(sel!(viewWillDisappear), will_disappear::<T> as extern "C" fn(&mut Object, _));
decl.add_method(sel!(viewDidDisappear), did_disappear::<T> as extern "C" fn(&mut Object, _));
})
}