cacao/appkit/window/controller/mod.rs

89 lines
2.9 KiB
Rust

use objc::runtime::Object;
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId;
use crate::foundation::{id, nil};
use crate::layout::traits::Layout;
use crate::window::{Window, WindowConfig, WindowDelegate, WINDOW_DELEGATE_PTR};
mod class;
use class::register_window_controller_class;
/// A `Window` represents your way of interacting with an `NSWindow`. It wraps the various moving
/// pieces to enable you to focus on reacting to lifecycle methods and doing your thing.
pub struct WindowController<T> {
pub objc: ShareId<Object>,
pub window: Window<T>
}
impl<T> WindowController<T> where T: WindowDelegate + 'static {
/// Allocates and configures an `NSWindowController` in the Objective-C/Cocoa runtime that maps over
/// to your supplied delegate.
pub fn with(config: WindowConfig, delegate: T) -> Self {
let mut window = Window::with(config, delegate);
let objc = unsafe {
let window_controller_class = register_window_controller_class::<T>();
let controller_alloc: id = msg_send![window_controller_class, alloc];
let controller: id = msg_send![controller_alloc, initWithWindow:&*window.objc];
if let Some(ptr) = window.internal_callback_ptr {
(&mut *controller).set_ivar(WINDOW_DELEGATE_PTR, ptr as usize);
}
ShareId::from_ptr(controller)
};
if let Some(window_delegate) = &mut window.delegate {
let mut window_delegate = window_delegate.borrow_mut();
(*window_delegate).did_load(Window {
internal_callback_ptr: None,
delegate: None,
objc: window.objc.clone()
});
}
WindowController {
objc: objc,
window: window
}
}
/// Sets the content view controller for the window.
pub fn set_content_view_controller<VC: Layout + 'static>(&self, view_controller: &VC) {
//self.objc_controller.set_content_view_controller(view_controller);
}
/// Shows the window, running a configuration pass if necessary.
pub fn show(&self) {
unsafe {
let _: () = msg_send![&*self.objc, showWindow:nil];
}
}
/// Closes the window.
pub fn close(&self) {
unsafe {
let _: () = msg_send![&*self.objc, close];
}
}
}
/*impl<T> Drop for Window<T> {
/// When a Window is dropped on the Rust side, we want to ensure that we break the delegate
/// link on the Objective-C side. While this shouldn't actually be an issue, I'd rather be
/// safer than sorry.
///
/// We also clean up our loopback pointer that we use for callbacks.
fn drop(&mut self) {
unsafe {
let window: id = msg_send![*objc_controller, window];
let _: () = msg_send![window, setDelegate:nil];
let _ = Rc::from_raw(self.internal_callback_ptr);
}
}
}*/