Skip to content

Commit

Permalink
feat: add set_accelerator (#64)
Browse files Browse the repository at this point in the history
* feat: add `set_accelerator`

closes #63

* unsafe
  • Loading branch information
amrbashir authored May 4, 2023
1 parent dfd7b9e commit 47ba0b4
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changes/set-accelerator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"muda": "minor"
---

Add `(MenuItem|CheckMenuItem|IconMenuItem)::set_accelerator` to change or disable the accelerator after creation.
2 changes: 2 additions & 0 deletions examples/tao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ fn main() {

if let Ok(event) = menu_channel.try_recv() {
if event.id == custom_i_1.id() {
custom_i_1
.set_accelerator(Some(Accelerator::new(Some(Modifiers::SHIFT), Code::KeyF)));
file_m.insert(&MenuItem::new("New Menu Item", true, None), 2);
}
println!("{event:?}");
Expand Down
5 changes: 5 additions & 0 deletions src/check_menu_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,9 @@ impl CheckMenuItem {
pub fn set_checked(&self, checked: bool) {
self.0.set_checked(checked)
}

/// Set this check menu item accelerator.
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.set_accelerator(acccelerator)
}
}
5 changes: 5 additions & 0 deletions src/icon_menu_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ impl IconMenuItem {
pub fn set_icon(&self, icon: Option<Icon>) {
self.0.set_icon(icon)
}

/// Set this icon menu item accelerator.
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.set_accelerator(acccelerator)
}
}
5 changes: 5 additions & 0 deletions src/menu_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,9 @@ impl MenuItem {
pub fn set_enabled(&self, enabled: bool) {
self.0.set_enabled(enabled)
}

/// Set this menu item accelerator.
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.set_accelerator(acccelerator)
}
}
10 changes: 10 additions & 0 deletions src/platform_impl/gtk/accelerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ pub fn register_accelerator<M: IsA<gtk::Widget>>(
}
}

pub fn remove_accelerator<M: IsA<gtk::Widget>>(
item: &M,
accel_group: &AccelGroup,
accelerator: &Accelerator,
) {
if let Ok((mods, key)) = parse_accelerator(accelerator) {
item.remove_accelerator(accel_group, key, mods);
}
}

fn modifiers_to_gdk_modifier_type(modifiers: Modifiers) -> gdk::ModifierType {
let mut result = gdk::ModifierType::empty();

Expand Down
36 changes: 35 additions & 1 deletion src/platform_impl/gtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use crate::{
util::{AddOp, Counter},
MenuEvent, MenuItemType,
};
use accelerator::{from_gtk_mnemonic, parse_accelerator, register_accelerator, to_gtk_mnemonic};
use accelerator::{
from_gtk_mnemonic, parse_accelerator, register_accelerator, remove_accelerator, to_gtk_mnemonic,
};
use gtk::{prelude::*, Orientation};
use std::{
cell::RefCell,
Expand Down Expand Up @@ -180,6 +182,20 @@ impl MenuChild {
}
}
}

fn set_accelerator(&mut self, accelerator: Option<Accelerator>) {
for items in self.gtk_menu_items.values() {
for i in items {
if let Some(accel) = self.accelerator {
remove_accelerator(i, self.accel_group.as_ref().unwrap(), &accel);
}
if let Some(accel) = accelerator.as_ref() {
register_accelerator(i, self.accel_group.as_ref().unwrap(), accel);
}
}
}
self.accelerator = accelerator;
}
}

struct InnerMenu {
Expand Down Expand Up @@ -818,6 +834,8 @@ impl MenuItem {
.sensitive(self_.enabled)
.build();

self_.accel_group = accel_group.cloned();

if let Some(accelerator) = &self_.accelerator {
if let Some(accel_group) = accel_group {
register_accelerator(&item, accel_group, accelerator);
Expand Down Expand Up @@ -858,6 +876,10 @@ impl MenuItem {
pub fn set_enabled(&self, enabled: bool) {
self.0.borrow_mut().set_enabled(enabled)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -1033,6 +1055,8 @@ impl CheckMenuItem {
.active(self_.checked)
.build();

self_.accel_group = accel_group.cloned();

if let Some(accelerator) = &self_.accelerator {
if let Some(accel_group) = accel_group {
register_accelerator(&item, accel_group, accelerator);
Expand Down Expand Up @@ -1111,6 +1135,10 @@ impl CheckMenuItem {
pub fn set_checked(&self, checked: bool) {
self.0.borrow_mut().set_checked(checked)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -1152,6 +1180,8 @@ impl IconMenuItem {
.map(|i| gtk::Image::from_pixbuf(Some(&i.inner.to_pixbuf(16, 16))))
.unwrap_or_else(gtk::Image::default);

self_.accel_group = accel_group.cloned();

let label = gtk::AccelLabel::builder()
.label(&to_gtk_mnemonic(&self_.text))
.use_underline(true)
Expand Down Expand Up @@ -1223,6 +1253,10 @@ impl IconMenuItem {
pub fn set_icon(&self, icon: Option<Icon>) {
self.0.borrow_mut().set_icon(icon)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

impl dyn crate::MenuItemExt + '_ {
Expand Down
40 changes: 40 additions & 0 deletions src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,34 @@ impl MenuChild {
}
}
}

fn set_accelerator(&mut self, accelerator: Option<Accelerator>) {
let key_equivalent = (accelerator)
.as_ref()
.map(|accel| accel.key_equivalent())
.unwrap_or_default();
let key_equivalent = unsafe {
NSString::alloc(nil)
.init_str(key_equivalent.as_str())
.autorelease()
};

let modifier_mask = (accelerator)
.as_ref()
.map(|accel| accel.key_modifier_mask())
.unwrap_or_else(NSEventModifierFlags::empty);

for ns_items in self.ns_menu_items.values() {
for &ns_item in ns_items {
unsafe {
let _: () = msg_send![ns_item, setKeyEquivalent: key_equivalent];
ns_item.setKeyEquivalentModifierMask_(modifier_mask);
}
}
}

self.accelerator = accelerator;
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -556,6 +584,10 @@ impl MenuItem {
pub fn set_enabled(&self, enabled: bool) {
self.0.borrow_mut().set_enabled(enabled)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -719,6 +751,10 @@ impl CheckMenuItem {
pub fn set_checked(&self, checked: bool) {
self.0.borrow_mut().set_checked(checked)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -798,6 +834,10 @@ impl IconMenuItem {
pub fn set_icon(&self, icon: Option<Icon>) {
self.0.borrow_mut().set_icon(icon)
}

pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
self.0.borrow_mut().set_accelerator(acccelerator)
}
}

impl PredfinedMenuItemType {
Expand Down
Loading

0 comments on commit 47ba0b4

Please sign in to comment.