2020-02-28 13:34:34 +11:00
|
|
|
//! Wraps NSMenu and handles instrumenting necessary delegate pieces.
|
|
|
|
|
|
|
|
use objc_id::Id;
|
|
|
|
use objc::runtime::Object;
|
|
|
|
use objc::{class, msg_send, sel, sel_impl};
|
|
|
|
|
2020-03-18 10:55:09 +11:00
|
|
|
use crate::foundation::{id, NSString};
|
2020-02-28 13:34:34 +11:00
|
|
|
use crate::menu::item::MenuItem;
|
|
|
|
|
|
|
|
/// A struct that represents an `NSMenu`. It takes ownership of items, and handles instrumenting
|
|
|
|
/// them throughout the application lifecycle.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Menu {
|
|
|
|
pub inner: Id<Object>,
|
|
|
|
pub items: Vec<MenuItem>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Menu {
|
|
|
|
/// Creates a new `Menu` with the given title, and uses the passed items as submenu items.
|
|
|
|
pub fn new(title: &str, items: Vec<MenuItem>) -> Self {
|
|
|
|
let inner = unsafe {
|
|
|
|
let cls = class!(NSMenu);
|
|
|
|
let alloc: id = msg_send![cls, alloc];
|
2020-03-18 10:55:09 +11:00
|
|
|
let title = NSString::new(title);
|
2020-02-28 13:34:34 +11:00
|
|
|
let inner: id = msg_send![alloc, initWithTitle:title];
|
|
|
|
Id::from_ptr(inner)
|
|
|
|
};
|
|
|
|
|
|
|
|
for item in items.iter() {
|
|
|
|
match item {
|
|
|
|
MenuItem::Action(item) => {
|
|
|
|
unsafe {
|
|
|
|
let _: () = msg_send![&*inner, addItem:item.clone()];
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
MenuItem::Separator => {
|
|
|
|
unsafe {
|
|
|
|
let cls = class!(NSMenuItem);
|
|
|
|
let separator: id = msg_send![cls, separatorItem];
|
|
|
|
let _: () = msg_send![&*inner, addItem:separator];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Menu {
|
|
|
|
inner: inner,
|
|
|
|
items: items
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|