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::runtime::Object;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
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::constants::APP_PTR;
|
||||||
use crate::menu::Menu;
|
use crate::menu::Menu;
|
||||||
|
|
||||||
|
@ -16,10 +16,18 @@ mod delegate;
|
||||||
use delegate::register_app_delegate_class;
|
use delegate::register_app_delegate_class;
|
||||||
|
|
||||||
pub mod enums;
|
pub mod enums;
|
||||||
|
pub use enums::AppDelegateResponse;
|
||||||
|
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub use traits::{AppDelegate, Dispatcher};
|
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,
|
/// 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 is where our application instance lives. It also injects an `NSObject` subclass,
|
||||||
/// which acts as the Delegate, looping back into our Vaulthund shared application.
|
/// 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>
|
_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 {
|
impl<T> App<T> where T: AppDelegate + 'static {
|
||||||
/// Creates an NSAutoReleasePool, configures various NSApplication properties (e.g, activation
|
/// Creates an NSAutoReleasePool, configures various NSApplication properties (e.g, activation
|
||||||
/// policies), injects an `NSObject` delegate wrapper, and retains everything on the
|
/// 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> {
|
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,
|
/// 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.
|
/// 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