More work on Application methods
This commit is contained in:
parent
f45c86743b
commit
e50bb25e9f
|
@ -29,3 +29,30 @@ impl From<TerminateResponse> for NSUInteger {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used for responding to open/print/copy requests.
|
||||
/// You only really need this for calling `App::reply_to_open_or_print()`.
|
||||
/// The name is unfortunate, but it covers a variety of things, and by keeping it closer to the
|
||||
/// `NSApplication` documentation it may help some poor soul who needs to find information about
|
||||
/// it.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AppDelegateResponse {
|
||||
/// Cancelled.
|
||||
Cancelled,
|
||||
|
||||
/// Success.
|
||||
Success,
|
||||
|
||||
/// Failed.
|
||||
Failure
|
||||
}
|
||||
|
||||
impl From<AppDelegateResponse> for NSUInteger {
|
||||
fn from(response: AppDelegateResponse) -> Self {
|
||||
match response {
|
||||
AppDelegateResponse::Cancelled => 1,
|
||||
AppDelegateResponse::Success => 0,
|
||||
AppDelegateResponse::Failure => 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use objc_id::Id;
|
|||
use objc::runtime::Object;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
|
||||
use crate::foundation::{id, AutoReleasePool};
|
||||
use crate::foundation::{id, YES, NO, NSUInteger, AutoReleasePool};
|
||||
use crate::constants::APP_PTR;
|
||||
use crate::menu::Menu;
|
||||
|
||||
|
@ -16,10 +16,18 @@ mod delegate;
|
|||
use delegate::register_app_delegate_class;
|
||||
|
||||
pub mod enums;
|
||||
pub use enums::AppDelegateResponse;
|
||||
|
||||
pub mod traits;
|
||||
pub use traits::{AppDelegate, Dispatcher};
|
||||
|
||||
/// A handler to make some boilerplate less annoying.
|
||||
#[inline]
|
||||
fn shared_application<F: Fn(id)>(handler: F) {
|
||||
let app: id = unsafe { msg_send![register_app_class(), sharedApplication] };
|
||||
handler(app);
|
||||
}
|
||||
|
||||
/// A wrapper for `NSApplication`. It holds (retains) pointers for the Objective-C runtime,
|
||||
/// which is where our application instance lives. It also injects an `NSObject` subclass,
|
||||
/// which acts as the Delegate, looping back into our Vaulthund shared application.
|
||||
|
@ -31,29 +39,6 @@ pub struct App<T = (), M = ()> {
|
|||
_t: std::marker::PhantomData<M>
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Sets a set of `Menu`'s as the top level Menu for the current application. Note that behind
|
||||
/// the scenes, Cocoa/AppKit make a copy of the menu you pass in - so we don't retain it, and
|
||||
/// you shouldn't bother to either.
|
||||
pub fn set_menu(menus: Vec<Menu>) {
|
||||
unsafe {
|
||||
let menu_cls = class!(NSMenu);
|
||||
let main_menu: id = msg_send![menu_cls, new];
|
||||
|
||||
let item_cls = class!(NSMenuItem);
|
||||
for menu in menus.iter() {
|
||||
let item: id = msg_send![item_cls, new];
|
||||
let _: () = msg_send![item, setSubmenu:&*menu.inner];
|
||||
let _: () = msg_send![main_menu, addItem:item];
|
||||
}
|
||||
|
||||
let cls = class!(RSTApplication);
|
||||
let shared_app: id = msg_send![cls, sharedApplication];
|
||||
let _: () = msg_send![shared_app, setMainMenu:main_menu];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> App<T> where T: AppDelegate + 'static {
|
||||
/// Creates an NSAutoReleasePool, configures various NSApplication properties (e.g, activation
|
||||
/// policies), injects an `NSObject` delegate wrapper, and retains everything on the
|
||||
|
@ -103,6 +88,7 @@ impl<T> App<T> where T: AppDelegate + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
// This is a hack and should be replaced with an actual messaging pipeline at some point. :)
|
||||
impl<T, M> App<T, M> where M: Send + Sync + 'static, T: AppDelegate + Dispatcher<Message = M> {
|
||||
/// Dispatches a message by grabbing the `sharedApplication`, getting ahold of the delegate,
|
||||
/// and passing back through there. All messages are currently dispatched on the main thread.
|
||||
|
@ -118,3 +104,68 @@ impl<T, M> App<T, M> where M: Send + Sync + 'static, T: AppDelegate + Dispatcher
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Registers for remote notifications from APNS.
|
||||
pub fn register_for_remote_notifications() {
|
||||
shared_application(|app| unsafe {
|
||||
let _: () = msg_send![app, registerForRemoteNotifications];
|
||||
});
|
||||
}
|
||||
|
||||
/// Unregisters for remote notifications from APNS.
|
||||
pub fn unregister_for_remote_notifications() {
|
||||
shared_application(|app| unsafe {
|
||||
let _: () = msg_send![app, unregisterForRemoteNotifications];
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets whether this application should relaunch at login.
|
||||
pub fn set_relaunch_on_login(relaunch: bool) {
|
||||
shared_application(|app| unsafe {
|
||||
if relaunch {
|
||||
let _: () = msg_send![app, enableRelaunchOnLogin];
|
||||
} else {
|
||||
let _: () = msg_send![app, disableRelaunchOnLogin];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Respond to a termination request. Generally done after returning `TerminateResponse::Later`
|
||||
/// from your trait implementation of `should_terminate()`.
|
||||
pub fn reply_to_termination_request(should_terminate: bool) {
|
||||
shared_application(|app| unsafe {
|
||||
let _: () = msg_send![app, replyToApplicationShouldTerminate:match should_terminate {
|
||||
true => YES,
|
||||
false => NO
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
/// An optional call that you can use for certain scenarios surrounding opening/printing files.
|
||||
pub fn reply_to_open_or_print(response: AppDelegateResponse) {
|
||||
shared_application(|app| unsafe {
|
||||
let r: NSUInteger = response.into();
|
||||
let _: () = msg_send![app, replyToOpenOrPrint:r];
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets a set of `Menu`'s as the top level Menu for the current application. Note that behind
|
||||
/// the scenes, Cocoa/AppKit make a copy of the menu you pass in - so we don't retain it, and
|
||||
/// you shouldn't bother to either.
|
||||
pub fn set_menu(menus: Vec<Menu>) {
|
||||
shared_application(|app| unsafe {
|
||||
let menu_cls = class!(NSMenu);
|
||||
let main_menu: id = msg_send![menu_cls, new];
|
||||
|
||||
let item_cls = class!(NSMenuItem);
|
||||
for menu in menus.iter() {
|
||||
let item: id = msg_send![item_cls, new];
|
||||
let _: () = msg_send![item, setSubmenu:&*menu.inner];
|
||||
let _: () = msg_send![main_menu, addItem:item];
|
||||
}
|
||||
|
||||
let _: () = msg_send![app, setMainMenu:main_menu];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue