mirror of
https://github.com/italicsjenga/muda.git
synced 2024-12-23 20:11:29 +11:00
feat: add set_accelerator
(#64)
* feat: add `set_accelerator` closes #63 * unsafe
This commit is contained in:
parent
dfd7b9e437
commit
47ba0b47ed
5
.changes/set-accelerator.md
Normal file
5
.changes/set-accelerator.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"muda": "minor"
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `(MenuItem|CheckMenuItem|IconMenuItem)::set_accelerator` to change or disable the accelerator after creation.
|
|
@ -189,6 +189,8 @@ fn main() {
|
||||||
|
|
||||||
if let Ok(event) = menu_channel.try_recv() {
|
if let Ok(event) = menu_channel.try_recv() {
|
||||||
if event.id == custom_i_1.id() {
|
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);
|
file_m.insert(&MenuItem::new("New Menu Item", true, None), 2);
|
||||||
}
|
}
|
||||||
println!("{event:?}");
|
println!("{event:?}");
|
||||||
|
|
|
@ -81,4 +81,9 @@ impl CheckMenuItem {
|
||||||
pub fn set_checked(&self, checked: bool) {
|
pub fn set_checked(&self, checked: bool) {
|
||||||
self.0.set_checked(checked)
|
self.0.set_checked(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set this check menu item accelerator.
|
||||||
|
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
|
||||||
|
self.0.set_accelerator(acccelerator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,4 +75,9 @@ impl IconMenuItem {
|
||||||
pub fn set_icon(&self, icon: Option<Icon>) {
|
pub fn set_icon(&self, icon: Option<Icon>) {
|
||||||
self.0.set_icon(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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,4 +63,9 @@ impl MenuItem {
|
||||||
pub fn set_enabled(&self, enabled: bool) {
|
pub fn set_enabled(&self, enabled: bool) {
|
||||||
self.0.set_enabled(enabled)
|
self.0.set_enabled(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set this menu item accelerator.
|
||||||
|
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
|
||||||
|
self.0.set_accelerator(acccelerator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
fn modifiers_to_gdk_modifier_type(modifiers: Modifiers) -> gdk::ModifierType {
|
||||||
let mut result = gdk::ModifierType::empty();
|
let mut result = gdk::ModifierType::empty();
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@ use crate::{
|
||||||
util::{AddOp, Counter},
|
util::{AddOp, Counter},
|
||||||
MenuEvent, MenuItemType,
|
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 gtk::{prelude::*, Orientation};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
@ -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 {
|
struct InnerMenu {
|
||||||
|
@ -818,6 +834,8 @@ impl MenuItem {
|
||||||
.sensitive(self_.enabled)
|
.sensitive(self_.enabled)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
self_.accel_group = accel_group.cloned();
|
||||||
|
|
||||||
if let Some(accelerator) = &self_.accelerator {
|
if let Some(accelerator) = &self_.accelerator {
|
||||||
if let Some(accel_group) = accel_group {
|
if let Some(accel_group) = accel_group {
|
||||||
register_accelerator(&item, accel_group, accelerator);
|
register_accelerator(&item, accel_group, accelerator);
|
||||||
|
@ -858,6 +876,10 @@ impl MenuItem {
|
||||||
pub fn set_enabled(&self, enabled: bool) {
|
pub fn set_enabled(&self, enabled: bool) {
|
||||||
self.0.borrow_mut().set_enabled(enabled)
|
self.0.borrow_mut().set_enabled(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
|
||||||
|
self.0.borrow_mut().set_accelerator(acccelerator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1033,6 +1055,8 @@ impl CheckMenuItem {
|
||||||
.active(self_.checked)
|
.active(self_.checked)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
self_.accel_group = accel_group.cloned();
|
||||||
|
|
||||||
if let Some(accelerator) = &self_.accelerator {
|
if let Some(accelerator) = &self_.accelerator {
|
||||||
if let Some(accel_group) = accel_group {
|
if let Some(accel_group) = accel_group {
|
||||||
register_accelerator(&item, accel_group, accelerator);
|
register_accelerator(&item, accel_group, accelerator);
|
||||||
|
@ -1111,6 +1135,10 @@ impl CheckMenuItem {
|
||||||
pub fn set_checked(&self, checked: bool) {
|
pub fn set_checked(&self, checked: bool) {
|
||||||
self.0.borrow_mut().set_checked(checked)
|
self.0.borrow_mut().set_checked(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
|
||||||
|
self.0.borrow_mut().set_accelerator(acccelerator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1152,6 +1180,8 @@ impl IconMenuItem {
|
||||||
.map(|i| gtk::Image::from_pixbuf(Some(&i.inner.to_pixbuf(16, 16))))
|
.map(|i| gtk::Image::from_pixbuf(Some(&i.inner.to_pixbuf(16, 16))))
|
||||||
.unwrap_or_else(gtk::Image::default);
|
.unwrap_or_else(gtk::Image::default);
|
||||||
|
|
||||||
|
self_.accel_group = accel_group.cloned();
|
||||||
|
|
||||||
let label = gtk::AccelLabel::builder()
|
let label = gtk::AccelLabel::builder()
|
||||||
.label(&to_gtk_mnemonic(&self_.text))
|
.label(&to_gtk_mnemonic(&self_.text))
|
||||||
.use_underline(true)
|
.use_underline(true)
|
||||||
|
@ -1223,6 +1253,10 @@ impl IconMenuItem {
|
||||||
pub fn set_icon(&self, icon: Option<Icon>) {
|
pub fn set_icon(&self, icon: Option<Icon>) {
|
||||||
self.0.borrow_mut().set_icon(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 + '_ {
|
impl dyn crate::MenuItemExt + '_ {
|
||||||
|
|
|
@ -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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -556,6 +584,10 @@ impl MenuItem {
|
||||||
pub fn set_enabled(&self, enabled: bool) {
|
pub fn set_enabled(&self, enabled: bool) {
|
||||||
self.0.borrow_mut().set_enabled(enabled)
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -719,6 +751,10 @@ impl CheckMenuItem {
|
||||||
pub fn set_checked(&self, checked: bool) {
|
pub fn set_checked(&self, checked: bool) {
|
||||||
self.0.borrow_mut().set_checked(checked)
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -798,6 +834,10 @@ impl IconMenuItem {
|
||||||
pub fn set_icon(&self, icon: Option<Icon>) {
|
pub fn set_icon(&self, icon: Option<Icon>) {
|
||||||
self.0.borrow_mut().set_icon(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 {
|
impl PredfinedMenuItemType {
|
||||||
|
|
|
@ -15,7 +15,12 @@ use crate::{
|
||||||
util::{AddOp, Counter},
|
util::{AddOp, Counter},
|
||||||
MenuEvent, MenuItemType,
|
MenuEvent, MenuItemType,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
use std::{
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::Debug,
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
use util::{decode_wide, encode_wide, Accel};
|
use util::{decode_wide, encode_wide, Accel};
|
||||||
use windows_sys::Win32::{
|
use windows_sys::Win32::{
|
||||||
Foundation::{HWND, LPARAM, LRESULT, POINT, WPARAM},
|
Foundation::{HWND, LPARAM, LRESULT, POINT, WPARAM},
|
||||||
|
@ -39,7 +44,7 @@ use windows_sys::Win32::{
|
||||||
const COUNTER_START: u32 = 1000;
|
const COUNTER_START: u32 = 1000;
|
||||||
static COUNTER: Counter = Counter::new_with_start(COUNTER_START);
|
static COUNTER: Counter = Counter::new_with_start(COUNTER_START);
|
||||||
|
|
||||||
type AccelWrapper = (HACCEL, Vec<Accel>);
|
type AccelWrapper = (HACCEL, HashMap<u32, Accel>);
|
||||||
|
|
||||||
/// A generic child in a menu
|
/// A generic child in a menu
|
||||||
///
|
///
|
||||||
|
@ -51,6 +56,7 @@ struct MenuChild {
|
||||||
text: String,
|
text: String,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
parents_hemnu: Vec<HMENU>,
|
parents_hemnu: Vec<HMENU>,
|
||||||
|
root_menu_haccel_stores: Option<Vec<Rc<RefCell<AccelWrapper>>>>,
|
||||||
|
|
||||||
// menu item fields
|
// menu item fields
|
||||||
id: u32,
|
id: u32,
|
||||||
|
@ -69,7 +75,6 @@ struct MenuChild {
|
||||||
hmenu: HMENU,
|
hmenu: HMENU,
|
||||||
hpopupmenu: HMENU,
|
hpopupmenu: HMENU,
|
||||||
children: Option<Vec<Rc<RefCell<MenuChild>>>>,
|
children: Option<Vec<Rc<RefCell<MenuChild>>>>,
|
||||||
root_menu_haccel: Option<Vec<Rc<RefCell<AccelWrapper>>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MenuChild {
|
impl MenuChild {
|
||||||
|
@ -104,12 +109,16 @@ impl MenuChild {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_text(&mut self, text: &str) {
|
fn set_text(&mut self, text: &str) {
|
||||||
self.text = text.to_string();
|
self.text = if let Some(accelerator) = self.accelerator {
|
||||||
|
format!("{text}\t{}", accelerator)
|
||||||
|
} else {
|
||||||
|
text.to_string()
|
||||||
|
};
|
||||||
for parent in &self.parents_hemnu {
|
for parent in &self.parents_hemnu {
|
||||||
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
|
let mut info: MENUITEMINFOW = unsafe { std::mem::zeroed() };
|
||||||
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
|
info.cbSize = std::mem::size_of::<MENUITEMINFOW>() as _;
|
||||||
info.fMask = MIIM_STRING;
|
info.fMask = MIIM_STRING;
|
||||||
info.dwTypeData = encode_wide(text).as_mut_ptr();
|
info.dwTypeData = encode_wide(&self.text).as_mut_ptr();
|
||||||
|
|
||||||
unsafe { SetMenuItemInfoW(*parent, self.id(), false.into(), &info) };
|
unsafe { SetMenuItemInfoW(*parent, self.id(), false.into(), &info) };
|
||||||
}
|
}
|
||||||
|
@ -182,6 +191,21 @@ impl MenuChild {
|
||||||
unsafe { SetMenuItemInfoW(*parent, self.id(), false.into(), &info) };
|
unsafe { SetMenuItemInfoW(*parent, self.id(), false.into(), &info) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_accelerator(&mut self, accelerator: Option<Accelerator>) {
|
||||||
|
self.accelerator = accelerator;
|
||||||
|
self.set_text(&self.text.clone());
|
||||||
|
|
||||||
|
let haccel_stores = self.root_menu_haccel_stores.as_mut().unwrap();
|
||||||
|
for store in haccel_stores {
|
||||||
|
let mut store = store.borrow_mut();
|
||||||
|
if let Some(accelerator) = self.accelerator {
|
||||||
|
AccelAction::add(&mut store, self.id, &accelerator)
|
||||||
|
} else {
|
||||||
|
AccelAction::remove(&mut store, self.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -189,7 +213,7 @@ pub(crate) struct Menu {
|
||||||
hmenu: HMENU,
|
hmenu: HMENU,
|
||||||
hpopupmenu: HMENU,
|
hpopupmenu: HMENU,
|
||||||
hwnds: Rc<RefCell<Vec<HWND>>>,
|
hwnds: Rc<RefCell<Vec<HWND>>>,
|
||||||
haccel: Rc<RefCell<(HACCEL, Vec<Accel>)>>,
|
haccel_store: Rc<RefCell<AccelWrapper>>,
|
||||||
children: Rc<RefCell<Vec<Rc<RefCell<MenuChild>>>>>,
|
children: Rc<RefCell<Vec<Rc<RefCell<MenuChild>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +222,7 @@ impl Menu {
|
||||||
Self {
|
Self {
|
||||||
hmenu: unsafe { CreateMenu() },
|
hmenu: unsafe { CreateMenu() },
|
||||||
hpopupmenu: unsafe { CreatePopupMenu() },
|
hpopupmenu: unsafe { CreatePopupMenu() },
|
||||||
haccel: Rc::new(RefCell::new((0, Vec::new()))),
|
haccel_store: Rc::new(RefCell::new((0, HashMap::new()))),
|
||||||
children: Rc::new(RefCell::new(Vec::new())),
|
children: Rc::new(RefCell::new(Vec::new())),
|
||||||
hwnds: Rc::new(RefCell::new(Vec::new())),
|
hwnds: Rc::new(RefCell::new(Vec::new())),
|
||||||
}
|
}
|
||||||
|
@ -212,12 +236,6 @@ impl Menu {
|
||||||
let child = &submenu.0 .0;
|
let child = &submenu.0 .0;
|
||||||
|
|
||||||
flags |= MF_POPUP;
|
flags |= MF_POPUP;
|
||||||
child
|
|
||||||
.borrow_mut()
|
|
||||||
.root_menu_haccel
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.push(self.haccel.clone());
|
|
||||||
|
|
||||||
child
|
child
|
||||||
}
|
}
|
||||||
|
@ -275,6 +293,15 @@ impl Menu {
|
||||||
}
|
}
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
{
|
||||||
|
child
|
||||||
|
.borrow_mut()
|
||||||
|
.root_menu_haccel_stores
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.push(self.haccel_store.clone());
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let child_ = child.borrow();
|
let child_ = child.borrow();
|
||||||
if !child_.enabled {
|
if !child_.enabled {
|
||||||
|
@ -285,15 +312,12 @@ impl Menu {
|
||||||
|
|
||||||
if let Some(accelerator) = &child_.accelerator {
|
if let Some(accelerator) = &child_.accelerator {
|
||||||
let accel_str = accelerator.to_string();
|
let accel_str = accelerator.to_string();
|
||||||
let accel = accelerator.to_accel(child_.id() as u16);
|
|
||||||
|
|
||||||
text.push('\t');
|
text.push('\t');
|
||||||
text.push_str(&accel_str);
|
text.push_str(&accel_str);
|
||||||
|
|
||||||
let mut haccel = self.haccel.borrow_mut();
|
let mut haccel_store = self.haccel_store.borrow_mut();
|
||||||
haccel.1.push(Accel(accel));
|
AccelAction::add(&mut haccel_store, child_.id(), accelerator);
|
||||||
let accels = haccel.1.clone();
|
|
||||||
update_haccel(&mut haccel.0, accels)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = child_.id() as usize;
|
let id = child_.id() as usize;
|
||||||
|
@ -461,7 +485,7 @@ impl Menu {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn haccel(&self) -> HACCEL {
|
pub fn haccel(&self) -> HACCEL {
|
||||||
self.haccel.borrow().0
|
self.haccel_store.borrow().0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hpopupmenu(&self) -> HMENU {
|
pub fn hpopupmenu(&self) -> HMENU {
|
||||||
|
@ -567,7 +591,7 @@ impl Submenu {
|
||||||
children: Some(Vec::new()),
|
children: Some(Vec::new()),
|
||||||
hmenu: unsafe { CreateMenu() },
|
hmenu: unsafe { CreateMenu() },
|
||||||
hpopupmenu: unsafe { CreatePopupMenu() },
|
hpopupmenu: unsafe { CreatePopupMenu() },
|
||||||
root_menu_haccel: Some(Vec::new()),
|
root_menu_haccel_stores: Some(Vec::new()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -589,13 +613,6 @@ impl Submenu {
|
||||||
|
|
||||||
flags |= MF_POPUP;
|
flags |= MF_POPUP;
|
||||||
|
|
||||||
child
|
|
||||||
.borrow_mut()
|
|
||||||
.root_menu_haccel
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.extend_from_slice(self.0.borrow_mut().root_menu_haccel.as_ref().unwrap());
|
|
||||||
|
|
||||||
child
|
child
|
||||||
}
|
}
|
||||||
MenuItemType::Normal => {
|
MenuItemType::Normal => {
|
||||||
|
@ -653,6 +670,21 @@ impl Submenu {
|
||||||
}
|
}
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
|
{
|
||||||
|
child
|
||||||
|
.borrow_mut()
|
||||||
|
.root_menu_haccel_stores
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.extend_from_slice(
|
||||||
|
self.0
|
||||||
|
.borrow_mut()
|
||||||
|
.root_menu_haccel_stores
|
||||||
|
.as_ref()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut self_ = self.0.borrow_mut();
|
let mut self_ = self.0.borrow_mut();
|
||||||
|
|
||||||
|
@ -665,16 +697,13 @@ impl Submenu {
|
||||||
|
|
||||||
if let Some(accelerator) = &child_.accelerator {
|
if let Some(accelerator) = &child_.accelerator {
|
||||||
let accel_str = accelerator.to_string();
|
let accel_str = accelerator.to_string();
|
||||||
let accel = accelerator.to_accel(child_.id() as u16);
|
|
||||||
|
|
||||||
text.push('\t');
|
text.push('\t');
|
||||||
text.push_str(&accel_str);
|
text.push_str(&accel_str);
|
||||||
|
|
||||||
for root_menu in self_.root_menu_haccel.as_mut().unwrap() {
|
for root_menu in self_.root_menu_haccel_stores.as_mut().unwrap() {
|
||||||
let mut haccel = root_menu.borrow_mut();
|
let mut haccel = root_menu.borrow_mut();
|
||||||
haccel.1.push(Accel(accel));
|
AccelAction::add(&mut haccel, child_.id(), accelerator);
|
||||||
let accels = haccel.1.clone();
|
|
||||||
update_haccel(&mut haccel.0, accels)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -895,6 +924,7 @@ impl MenuItem {
|
||||||
parents_hemnu: Vec::new(),
|
parents_hemnu: Vec::new(),
|
||||||
id: COUNTER.next(),
|
id: COUNTER.next(),
|
||||||
accelerator,
|
accelerator,
|
||||||
|
root_menu_haccel_stores: Some(Vec::new()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -918,6 +948,10 @@ impl MenuItem {
|
||||||
pub fn set_enabled(&self, enabled: bool) {
|
pub fn set_enabled(&self, enabled: bool) {
|
||||||
self.0.borrow_mut().set_enabled(enabled)
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -933,6 +967,7 @@ impl PredefinedMenuItem {
|
||||||
id: COUNTER.next(),
|
id: COUNTER.next(),
|
||||||
accelerator: item_type.accelerator(),
|
accelerator: item_type.accelerator(),
|
||||||
predefined_item_type: item_type,
|
predefined_item_type: item_type,
|
||||||
|
root_menu_haccel_stores: Some(Vec::new()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -963,6 +998,7 @@ impl CheckMenuItem {
|
||||||
id: COUNTER.next(),
|
id: COUNTER.next(),
|
||||||
accelerator,
|
accelerator,
|
||||||
checked,
|
checked,
|
||||||
|
root_menu_haccel_stores: Some(Vec::new()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -994,6 +1030,10 @@ impl CheckMenuItem {
|
||||||
pub fn set_checked(&self, checked: bool) {
|
pub fn set_checked(&self, checked: bool) {
|
||||||
self.0.borrow_mut().set_checked(checked)
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -1014,6 +1054,7 @@ impl IconMenuItem {
|
||||||
id: COUNTER.next(),
|
id: COUNTER.next(),
|
||||||
accelerator,
|
accelerator,
|
||||||
icon,
|
icon,
|
||||||
|
root_menu_haccel_stores: Some(Vec::new()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
@ -1041,6 +1082,10 @@ impl IconMenuItem {
|
||||||
pub fn set_icon(&self, icon: Option<Icon>) {
|
pub fn set_icon(&self, icon: Option<Icon>) {
|
||||||
self.0.borrow_mut().set_icon(icon)
|
self.0.borrow_mut().set_icon(icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_accelerator(&self, acccelerator: Option<Accelerator>) {
|
||||||
|
self.0.borrow_mut().set_accelerator(acccelerator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MENU_SUBCLASS_ID: usize = 200;
|
const MENU_SUBCLASS_ID: usize = 200;
|
||||||
|
@ -1183,15 +1228,36 @@ unsafe extern "system" fn menu_subclass_proc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_haccel(haccel: &mut HMENU, accels: Vec<Accel>) {
|
struct AccelAction;
|
||||||
|
|
||||||
|
impl AccelAction {
|
||||||
|
fn add(haccel_store: &mut RefMut<AccelWrapper>, id: u32, accelerator: &Accelerator) {
|
||||||
|
let accel = accelerator.to_accel(id as _);
|
||||||
|
haccel_store.1.insert(id, Accel(accel));
|
||||||
|
|
||||||
|
Self::update_store(haccel_store)
|
||||||
|
}
|
||||||
|
fn remove(haccel_store: &mut RefMut<AccelWrapper>, id: u32) {
|
||||||
|
haccel_store.1.remove(&id);
|
||||||
|
|
||||||
|
Self::update_store(haccel_store)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_store(haccel_store: &mut RefMut<AccelWrapper>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
DestroyAcceleratorTable(*haccel);
|
DestroyAcceleratorTable(haccel_store.0);
|
||||||
*haccel = CreateAcceleratorTableW(
|
haccel_store.0 = CreateAcceleratorTableW(
|
||||||
accels.iter().map(|i| i.0).collect::<Vec<_>>().as_ptr(),
|
haccel_store
|
||||||
accels.len() as _,
|
.1
|
||||||
|
.values()
|
||||||
|
.map(|i| i.0)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.as_ptr(),
|
||||||
|
haccel_store.1.len() as _,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn show_context_menu(hwnd: HWND, hmenu: HMENU, x: f64, y: f64) {
|
fn show_context_menu(hwnd: HWND, hmenu: HMENU, x: f64, y: f64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
Loading…
Reference in a new issue