mirror of
https://github.com/italicsjenga/muda.git
synced 2025-01-27 03:26:34 +11:00
feat(macos): implement CheckMenuItem
, NativeMenuItem
(#14)
* feat(macos): implement `CheckMenuItem` * feat(macos): implement `NativeMenuItem` * Update src/platform_impl/macos/mod.rs Co-authored-by: Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com> * Fix enum variant Co-authored-by: Ngo Iok Ui (Wu Yu Wei) <wusyong9104@gmail.com>
This commit is contained in:
parent
00a0270b8f
commit
a125e8a58c
2 changed files with 171 additions and 7 deletions
|
@ -82,6 +82,93 @@ impl MenuItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CheckMenuItem {
|
||||
pub(crate) id: u64,
|
||||
pub(crate) ns_menu_item: id,
|
||||
label: Rc<str>,
|
||||
}
|
||||
|
||||
impl CheckMenuItem {
|
||||
pub fn new<S: AsRef<str>>(
|
||||
label: S,
|
||||
enabled: bool,
|
||||
checked: bool,
|
||||
selector: Sel,
|
||||
accelerator: Option<&str>,
|
||||
) -> Self {
|
||||
let (id, ns_menu_item) = make_menu_item(&remove_mnemonic(&label), selector, accelerator);
|
||||
|
||||
unsafe {
|
||||
(&mut *ns_menu_item).set_ivar(MENU_IDENTITY, id);
|
||||
let () = msg_send![&*ns_menu_item, setTarget:&*ns_menu_item];
|
||||
|
||||
if !enabled {
|
||||
let () = msg_send![ns_menu_item, setEnabled: NO];
|
||||
}
|
||||
|
||||
if checked {
|
||||
let () = msg_send![ns_menu_item, setState: 1_isize];
|
||||
}
|
||||
}
|
||||
Self {
|
||||
id,
|
||||
ns_menu_item,
|
||||
label: Rc::from(label.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label(&self) -> String {
|
||||
self.label.to_string()
|
||||
}
|
||||
|
||||
pub fn set_label<S: AsRef<str>>(&mut self, label: S) {
|
||||
unsafe {
|
||||
let title = NSString::alloc(nil).init_str(&remove_mnemonic(&label));
|
||||
self.ns_menu_item.setTitle_(title);
|
||||
}
|
||||
self.label = Rc::from(label.as_ref());
|
||||
}
|
||||
|
||||
pub fn enabled(&self) -> bool {
|
||||
unsafe {
|
||||
let enabled: BOOL = msg_send![self.ns_menu_item, isEnabled];
|
||||
enabled == YES
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_enabled(&mut self, enabled: bool) {
|
||||
unsafe {
|
||||
let status = match enabled {
|
||||
true => YES,
|
||||
false => NO,
|
||||
};
|
||||
let () = msg_send![self.ns_menu_item, setEnabled: status];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checked(&self) -> bool {
|
||||
unsafe {
|
||||
let checked: isize = msg_send![self.ns_menu_item, state];
|
||||
checked == 1_isize
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_checked(&mut self, checked: bool) {
|
||||
unsafe {
|
||||
let state = match checked {
|
||||
true => 1_isize,
|
||||
false => 0_isize,
|
||||
};
|
||||
let () = msg_send![self.ns_menu_item, setState: state];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u64 {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_menu_item(title: &str, selector: Sel, accelerator: Option<&str>) -> (u64, *mut Object) {
|
||||
let alloc = make_menu_item_alloc();
|
||||
let menu_id = COUNTER.next();
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
mod accelerator;
|
||||
mod menu_item;
|
||||
|
||||
use crate::platform_impl::platform_impl::menu_item::make_menu_item;
|
||||
use crate::NativeMenuItem;
|
||||
use cocoa::{
|
||||
appkit::{NSApp, NSApplication, NSMenu, NSMenuItem},
|
||||
base::{id, nil, NO},
|
||||
base::{id, nil, selector, NO},
|
||||
foundation::{NSAutoreleasePool, NSString},
|
||||
};
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
|
||||
pub use menu_item::MenuItem;
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
|
||||
use self::accelerator::remove_mnemonic;
|
||||
pub use menu_item::CheckMenuItem;
|
||||
pub use menu_item::MenuItem;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Menu(id);
|
||||
|
@ -98,8 +99,84 @@ impl Submenu {
|
|||
item
|
||||
}
|
||||
|
||||
pub fn add_native_item(&mut self, _item: NativeMenuItem) {
|
||||
// TODO
|
||||
return;
|
||||
pub fn add_native_item(&mut self, item: NativeMenuItem) {
|
||||
let (_, native_menu_item) = match item {
|
||||
NativeMenuItem::Separator => unsafe { (0, NSMenuItem::separatorItem(nil)) },
|
||||
NativeMenuItem::About(app_name, _) => {
|
||||
let title = format!("About {}", app_name);
|
||||
make_menu_item(
|
||||
title.as_str(),
|
||||
selector("orderFrontStandardAboutPanel:"),
|
||||
None,
|
||||
)
|
||||
}
|
||||
NativeMenuItem::CloseWindow => {
|
||||
make_menu_item("Close Window", selector("performClose:"), Some("Command+W"))
|
||||
}
|
||||
NativeMenuItem::Quit => {
|
||||
make_menu_item("Quit", selector("terminate:"), Some("Command+Q"))
|
||||
}
|
||||
NativeMenuItem::Hide => make_menu_item("Hide", selector("hide:"), Some("Command+H")),
|
||||
NativeMenuItem::HideOthers => make_menu_item(
|
||||
"Hide Others",
|
||||
selector("hideOtherApplications:"),
|
||||
Some("Alt+H"),
|
||||
),
|
||||
NativeMenuItem::ShowAll => {
|
||||
make_menu_item("Show All", selector("unhideAllApplications:"), None)
|
||||
}
|
||||
NativeMenuItem::EnterFullScreen => make_menu_item(
|
||||
"Toggle Full Screen",
|
||||
selector("toggleFullScreen:"),
|
||||
Some("Ctrl+F"),
|
||||
),
|
||||
NativeMenuItem::Minimize => make_menu_item(
|
||||
"Minimize",
|
||||
selector("performMiniaturize:"),
|
||||
Some("Command+M"),
|
||||
),
|
||||
NativeMenuItem::Zoom => make_menu_item("Zoom", selector("performZoom:"), None),
|
||||
NativeMenuItem::Copy => make_menu_item("Copy", selector("copy:"), Some("Command+C")),
|
||||
NativeMenuItem::Cut => make_menu_item("Cut", selector("cut:"), Some("Command+X")),
|
||||
NativeMenuItem::Paste => make_menu_item("Paste", selector("paste:"), Some("Command+V")),
|
||||
NativeMenuItem::Undo => make_menu_item("Undo", selector("undo:"), Some("Command+Z")),
|
||||
NativeMenuItem::Redo => {
|
||||
make_menu_item("Redo", selector("redo:"), Some("Command+Shift+Z"))
|
||||
}
|
||||
NativeMenuItem::SelectAll => {
|
||||
make_menu_item("Select All", selector("selectAll:"), Some("Command+A"))
|
||||
}
|
||||
NativeMenuItem::Services => unsafe {
|
||||
let (_, item) = make_menu_item("Services", sel!(fireMenubarAction:), None);
|
||||
let app_class = class!(NSApplication);
|
||||
let app: id = msg_send![app_class, sharedApplication];
|
||||
let services: id = msg_send![app, servicesMenu];
|
||||
let _: () = msg_send![&*item, setSubmenu: services];
|
||||
(0, item)
|
||||
},
|
||||
};
|
||||
unsafe {
|
||||
self.menu.0.addItem_(native_menu_item);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_check_item<S: AsRef<str>>(
|
||||
&mut self,
|
||||
label: S,
|
||||
enabled: bool,
|
||||
checked: bool,
|
||||
accelerator: Option<&str>,
|
||||
) -> CheckMenuItem {
|
||||
let item = CheckMenuItem::new(
|
||||
label,
|
||||
enabled,
|
||||
checked,
|
||||
sel!(fireMenubarAction:),
|
||||
accelerator,
|
||||
);
|
||||
unsafe {
|
||||
self.menu.0.addItem_(item.ns_menu_item);
|
||||
}
|
||||
item
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue