#![allow(trivial_casts)]
use std::sync::Once;
use objc::{class, declare::ClassDecl};
use crate::{
core_graphics::CGSize,
foundation::{NSRect, NSSize},
objective_c_runtime::{
id,
runtime::{Class, Object, Sel},
sel, sel_impl,
},
};
use super::{NSWindow, NSWINDOW_DELEGATE_PTR};
pub trait PNSWindowDelegate {
const NAME: &'static str;
fn subclass_name(&self) -> &'static str {
Self::NAME
}
fn im_window_will_position_sheet_using_rect(
_window: NSWindow,
_sheet: NSWindow,
_rect: NSRect,
) -> NSRect {
NSRect::default()
}
fn im_will_begin_sheet(&self) {}
fn im_did_end_sheet(&self) {}
fn im_will_resize_to_size(&self, frame_size: NSSize) -> NSSize {
frame_size
}
fn im_did_resize(&self) {}
fn im_will_start_live_resize(&self) {}
fn im_did_end_live_resize(&self) {}
fn im_will_miniaturize(&self) {}
fn im_did_miniaturize(&self) {}
fn im_did_deminiaturize(&self) {}
fn im_will_enter_full_screen(&self) {}
fn im_did_enter_full_screen(&self) {}
fn im_will_exit_full_screen(&self) {}
fn im_did_exit_full_screen(&self) {}
fn im_did_fail_to_enter_full_screen(&self) {}
fn im_did_fail_to_exit_full_screen(&self) {}
fn im_will_move(&self) {}
fn im_did_move(&self) {}
fn im_did_change_screen(&self) {}
fn im_did_change_screen_profile(&self) {}
fn im_did_change_backing_properties(&self) {}
fn im_should_close(&self) -> bool {
true
}
fn im_will_close(&self) {}
fn im_did_become_key(&self) {}
fn im_did_resign_key(&self) {}
fn im_did_become_main(&self) {}
fn im_did_resign_main(&self) {}
fn im_did_update(&self) {}
fn im_did_expose(&self) {}
fn im_did_change_occlusion_state(&self) {}
fn did_load(&mut self, _window: NSWindow) {}
fn content_size_for_full_screen(
&self,
proposed_width: f64,
proposed_height: f64,
) -> (f64, f64) {
(proposed_width, proposed_height)
}
fn cancel(&self) {}
}
fn load<'a, T>(this: &'a Object, ptr_name: &str) -> &'a T {
unsafe {
let ptr: usize = *this.get_ivar(ptr_name);
let obj = ptr as *const T;
&*obj
}
}
extern "C" fn should_close<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) -> bool {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_should_close()
}
extern "C" fn will_close<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_close();
}
extern "C" fn will_move<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_move();
}
extern "C" fn did_move<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_move();
}
extern "C" fn did_change_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_change_screen();
}
extern "C" fn did_change_screen_profile<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_change_screen_profile();
}
extern "C" fn will_resize<T: PNSWindowDelegate>(
this: &Object,
_: Sel,
_: id,
size: CGSize,
) -> CGSize {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_resize_to_size(size)
}
extern "C" fn did_resize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_resize();
}
extern "C" fn will_start_live_resize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_start_live_resize();
}
extern "C" fn did_end_live_resize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_end_live_resize();
}
extern "C" fn will_miniaturize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_miniaturize();
}
extern "C" fn did_miniaturize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_miniaturize();
}
extern "C" fn did_deminiaturize<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_deminiaturize();
}
extern "C" fn will_enter_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_enter_full_screen();
}
extern "C" fn did_enter_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_enter_full_screen();
}
extern "C" fn content_size_for_full_screen<T: PNSWindowDelegate>(
this: &Object,
_: Sel,
_: id,
size: CGSize,
) -> CGSize {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
let (width, height) = window.content_size_for_full_screen(size.width, size.height);
CGSize { width, height }
}
extern "C" fn will_exit_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_will_exit_full_screen();
}
extern "C" fn did_exit_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_exit_full_screen();
}
extern "C" fn did_fail_to_enter_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_fail_to_enter_full_screen();
}
extern "C" fn did_fail_to_exit_full_screen<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_fail_to_exit_full_screen();
}
extern "C" fn did_change_backing_properties<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_change_backing_properties();
}
extern "C" fn did_change_occlusion_state<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_change_occlusion_state();
}
extern "C" fn did_update<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_update();
}
extern "C" fn did_become_main<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_become_main();
}
extern "C" fn did_resign_main<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_resign_main();
}
extern "C" fn did_become_key<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_become_key();
}
extern "C" fn did_resign_key<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_resign_key();
}
extern "C" fn did_expose<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.im_did_expose();
}
extern "C" fn cancel<T: PNSWindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, NSWINDOW_DELEGATE_PTR);
window.cancel();
}
pub(crate) fn register_window_class_with_delegate<T: PNSWindowDelegate>() -> *const Class {
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
let superclass = class!(NSWindow);
let mut decl = ClassDecl::new("RSTNSWindowDelegate", superclass).unwrap();
decl.add_ivar::<usize>(NSWINDOW_DELEGATE_PTR);
decl.add_method(
sel!(windowShouldClose:),
should_close::<T> as extern "C" fn(&Object, _, _) -> bool,
);
decl.add_method(
sel!(windowWillClose:),
will_close::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowWillResize:toSize:),
will_resize::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize,
);
decl.add_method(
sel!(windowDidResize:),
did_resize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowWillStartLiveResize:),
will_start_live_resize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidEndLiveResize:),
did_end_live_resize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowWillMiniaturize:),
will_miniaturize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidMiniaturize:),
did_miniaturize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidDeminiaturize:),
did_deminiaturize::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(window:willUseFullScreenContentSize:),
content_size_for_full_screen::<T> as extern "C" fn(&Object, _, _, CGSize) -> CGSize,
);
decl.add_method(
sel!(windowWillEnterFullScreen:),
will_enter_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidEnterFullScreen:),
did_enter_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowWillExitFullScreen:),
will_exit_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidExitFullScreen:),
did_exit_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidFailToEnterFullScreen:),
did_fail_to_enter_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidFailToExitFullScreen:),
did_fail_to_exit_full_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidBecomeKey:),
did_become_key::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidResignKey:),
did_resign_key::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidBecomeMain:),
did_become_main::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidResignMain:),
did_resign_main::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowWillMove:),
will_move::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidMove:),
did_move::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidChangeScreen:),
did_change_screen::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidChangeScreenProfile:),
did_change_screen_profile::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidChangeBackingProperties:),
did_change_backing_properties::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidChangeOcclusionState:),
did_change_occlusion_state::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidExpose:),
did_expose::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(windowDidUpdate:),
did_update::<T> as extern "C" fn(&Object, _, _),
);
decl.add_method(
sel!(cancelOperation:),
cancel::<T> as extern "C" fn(&Object, _, _),
);
});
unsafe { DELEGATE_CLASS }
}