mirror of
https://github.com/italicsjenga/muda.git
synced 2024-12-23 20:11:29 +11:00
add dedicated ns_menu for context menus and such
This commit is contained in:
parent
37153b826f
commit
35912d699d
|
@ -27,7 +27,7 @@ static BLOCK_PTR: &str = "mudaMenuItemBlockPtr";
|
||||||
/// A generic child in a menu
|
/// A generic child in a menu
|
||||||
///
|
///
|
||||||
/// Be careful when cloning this item and treat it as read-only
|
/// Be careful when cloning this item and treat it as read-only
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct MenuChild {
|
struct MenuChild {
|
||||||
// shared fields between submenus and menu items
|
// shared fields between submenus and menu items
|
||||||
|
@ -50,6 +50,25 @@ struct MenuChild {
|
||||||
// submenu fields
|
// submenu fields
|
||||||
children: Option<Vec<Rc<RefCell<MenuChild>>>>,
|
children: Option<Vec<Rc<RefCell<MenuChild>>>>,
|
||||||
ns_menus: HashMap<u32, Vec<id>>,
|
ns_menus: HashMap<u32, Vec<id>>,
|
||||||
|
ns_menu: (u32, id),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MenuChild {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
type_: Default::default(),
|
||||||
|
id: Default::default(),
|
||||||
|
text: Default::default(),
|
||||||
|
enabled: Default::default(),
|
||||||
|
ns_menu_items: Default::default(),
|
||||||
|
accelerator: Default::default(),
|
||||||
|
predefined_item_type: Default::default(),
|
||||||
|
checked: Default::default(),
|
||||||
|
children: Default::default(),
|
||||||
|
ns_menus: Default::default(),
|
||||||
|
ns_menu: (0, 0 as _),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MenuChild {
|
impl MenuChild {
|
||||||
|
@ -258,6 +277,7 @@ impl Submenu {
|
||||||
text: strip_mnemonic(text),
|
text: strip_mnemonic(text),
|
||||||
enabled,
|
enabled,
|
||||||
children: Some(Vec::new()),
|
children: Some(Vec::new()),
|
||||||
|
ns_menu: (COUNTER.next(), unsafe { NSMenu::alloc(nil).autorelease() }),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -339,6 +359,10 @@ impl Submenu {
|
||||||
ns_menu.addItem_(ns_menu_item);
|
ns_menu.addItem_(ns_menu_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ns_menu_item: *mut Object = item.make_ns_item_for_menu(self_.ns_menu.0);
|
||||||
|
self_.ns_menu.1.addItem_(ns_menu_item);
|
||||||
|
|
||||||
self_.children.as_mut().unwrap().push(item_child);
|
self_.children.as_mut().unwrap().push(item_child);
|
||||||
}
|
}
|
||||||
AddOp::Insert(position) => {
|
AddOp::Insert(position) => {
|
||||||
|
@ -348,6 +372,10 @@ impl Submenu {
|
||||||
let () = msg_send![ns_menu, insertItem: ns_menu_item atIndex: position as NSInteger];
|
let () = msg_send![ns_menu, insertItem: ns_menu_item atIndex: position as NSInteger];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ns_menu_item: *mut Object = item.make_ns_item_for_menu(self_.ns_menu.0);
|
||||||
|
let () = msg_send![ self_.ns_menu.1, insertItem: ns_menu_item atIndex: position as NSInteger];
|
||||||
|
|
||||||
self_
|
self_
|
||||||
.children
|
.children
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -359,29 +387,39 @@ impl Submenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&self, item: &dyn crate::MenuItemExt) -> crate::Result<()> {
|
pub fn remove(&self, item: &dyn crate::MenuItemExt) -> crate::Result<()> {
|
||||||
let mut child = self.0.borrow_mut();
|
let mut self_ = self.0.borrow_mut();
|
||||||
|
|
||||||
let item_child: Rc<RefCell<MenuChild>> = item.get_child();
|
let child: Rc<RefCell<MenuChild>> = item.get_child();
|
||||||
|
|
||||||
// get a list of instances of the specified NSMenuItem in this menu
|
// get a list of instances of the specified NSMenuItem in this menu
|
||||||
if let Some(ns_menu_items) = item_child.borrow_mut().ns_menu_items.remove(&child.id) {
|
if let Some(ns_menu_items) = child.borrow_mut().ns_menu_items.remove(&self_.id) {
|
||||||
// remove each NSMenuItem from the NSMenu
|
// remove each NSMenuItem from the NSMenu
|
||||||
unsafe {
|
unsafe {
|
||||||
for item in ns_menu_items {
|
for item in ns_menu_items {
|
||||||
for menus in child.ns_menus.values() {
|
for menus in self_.ns_menus.values() {
|
||||||
for &ns_menu in menus {
|
for &ns_menu in menus {
|
||||||
let () = msg_send![ns_menu, removeItem: item];
|
let () = msg_send![ns_menu, removeItem: item];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let () = msg_send![self_.ns_menu.1, removeItem: item];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ns_menu_items) = child.borrow_mut().ns_menu_items.remove(&self_.ns_menu.0) {
|
||||||
|
unsafe {
|
||||||
|
for item in ns_menu_items {
|
||||||
|
let () = msg_send![self_.ns_menu.1, removeItem: item];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the item from our internal list of children
|
// remove the item from our internal list of children
|
||||||
let children = child.children.as_mut().unwrap();
|
let children = self_.children.as_mut().unwrap();
|
||||||
let index = children
|
let index = children
|
||||||
.iter()
|
.iter()
|
||||||
.position(|e| e == &item_child)
|
.position(|e| e == &child)
|
||||||
.ok_or(crate::Error::NotAChildOfThisMenu)?;
|
.ok_or(crate::Error::NotAChildOfThisMenu)?;
|
||||||
children.remove(index);
|
children.remove(index);
|
||||||
|
|
||||||
|
@ -426,42 +464,26 @@ impl Submenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_context_menu_for_nsview(&self, view: id, x: f64, y: f64) {
|
pub fn show_context_menu_for_nsview(&self, view: id, x: f64, y: f64) {
|
||||||
// TODO: this needs to work even if it hasn't already been added to a menu
|
unsafe {
|
||||||
if let Some(ns_menus) = self.0.borrow().ns_menus.get(&1) {
|
let window: id = msg_send![view, window];
|
||||||
unsafe {
|
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
|
||||||
let window: id = msg_send![view, window];
|
let view_point = NSPoint::new(x / scale_factor, y / scale_factor);
|
||||||
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
|
let view_rect: NSRect = msg_send![view, frame];
|
||||||
let view_point = NSPoint::new(x / scale_factor, y / scale_factor);
|
let location = NSPoint::new(view_point.x, view_rect.size.height - view_point.y);
|
||||||
let view_rect: NSRect = msg_send![view, frame];
|
msg_send![self.0.borrow().ns_menu.1, popUpMenuPositioningItem: nil atLocation: location inView: view]
|
||||||
let location = NSPoint::new(view_point.x, view_rect.size.height - view_point.y);
|
|
||||||
msg_send![ns_menus[0], popUpMenuPositioningItem: nil atLocation: location inView: view]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_windows_menu_for_nsapp(&self) {
|
pub fn set_windows_menu_for_nsapp(&self) {
|
||||||
if let Some(ns_menus) = self.0.borrow().ns_menus.get(&1) {
|
unsafe { NSApp().setWindowsMenu_(self.0.borrow().ns_menu.1) }
|
||||||
unsafe { NSApp().setWindowsMenu_(ns_menus[0]) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_help_menu_for_nsapp(&self) {
|
pub fn set_help_menu_for_nsapp(&self) {
|
||||||
if let Some(ns_menus) = self.0.borrow().ns_menus.get(&1) {
|
unsafe { msg_send![NSApp(), setHelpMenu: self.0.borrow().ns_menu.1] }
|
||||||
unsafe { msg_send![NSApp(), setHelpMenu: ns_menus[0]] }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ns_menu(&self) -> *mut std::ffi::c_void {
|
pub fn ns_menu(&self) -> *mut std::ffi::c_void {
|
||||||
*self
|
self.0.borrow().ns_menu.1 as _
|
||||||
.0
|
|
||||||
.borrow()
|
|
||||||
.ns_menus
|
|
||||||
.values()
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.get(0)
|
|
||||||
.unwrap()
|
|
||||||
.get(0)
|
|
||||||
.unwrap() as _
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue