mirror of
https://github.com/italicsjenga/muda.git
synced 2025-01-11 12:21:30 +11:00
refactor: allow changing the menu event sender (#35)
* refactor: allow changing the menu event sender * readme * fix docs warning * readme
This commit is contained in:
parent
1e87714759
commit
f871c68e81
5
.changes/event_handler.md
Normal file
5
.changes/event_handler.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"muda": "patch"
|
||||
---
|
||||
|
||||
Add `MenuEvent::set_event_handler` to set a handler for new menu events.
|
5
.changes/rm-menu-event-receiver.md
Normal file
5
.changes/rm-menu-event-receiver.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"muda": "minor"
|
||||
---
|
||||
|
||||
**Breaking change** Remove `menu_event_receiver` function, use `MenuEvent::receiver` instead.
|
|
@ -52,10 +52,10 @@ menu.show_context_menu_for_nsview(nsview, x, y);
|
|||
```
|
||||
## Processing menu events
|
||||
|
||||
You can use [`menu_event_receiver`](https://docs.rs/muda/latest/muda/fn.menu_event_receiver.html) to get a reference to the [`MenuEventReceiver`](https://docs.rs/muda/latest/muda/type.MenuEventReceiver.html)
|
||||
You can use `MenuEvent::receiver` to get a reference to the `MenuEventReceiver`
|
||||
which you can use to listen to events when a menu item is activated
|
||||
```rs
|
||||
if let Ok(event) = menu_event_receiver().try_recv() {
|
||||
if let Ok(event) = MenuEvent::receiver().try_recv() {
|
||||
match event.id {
|
||||
_ if event.id == save_item.id() => {
|
||||
println!("Save menu item activated");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#![allow(unused)]
|
||||
use muda::{
|
||||
accelerator::{Accelerator, Code, Modifiers},
|
||||
menu_event_receiver, AboutMetadata, CheckMenuItem, ContextMenu, IconMenuItem, Menu, MenuItem,
|
||||
AboutMetadata, CheckMenuItem, ContextMenu, IconMenuItem, Menu, MenuEvent, MenuItem,
|
||||
PredefinedMenuItem, Submenu,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -144,7 +144,7 @@ fn main() {
|
|||
window_m.set_windows_menu_for_nsapp();
|
||||
}
|
||||
|
||||
let menu_channel = menu_event_receiver();
|
||||
let menu_channel = MenuEvent::receiver();
|
||||
|
||||
let mut x = 0_f64;
|
||||
let mut y = 0_f64;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#![allow(unused)]
|
||||
use muda::{
|
||||
accelerator::{Accelerator, Code, Modifiers},
|
||||
menu_event_receiver, AboutMetadata, CheckMenuItem, ContextMenu, IconMenuItem, Menu, MenuItem,
|
||||
AboutMetadata, CheckMenuItem, ContextMenu, IconMenuItem, Menu, MenuEvent, MenuItem,
|
||||
PredefinedMenuItem, Submenu,
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -136,7 +136,7 @@ fn main() {
|
|||
window_m.set_windows_menu_for_nsapp();
|
||||
}
|
||||
|
||||
let menu_channel = menu_event_receiver();
|
||||
let menu_channel = MenuEvent::receiver();
|
||||
|
||||
let mut x = 0_f64;
|
||||
let mut y = 0_f64;
|
||||
|
|
44
src/lib.rs
44
src/lib.rs
|
@ -79,13 +79,13 @@
|
|||
//! ```
|
||||
//! # Processing menu events
|
||||
//!
|
||||
//! You can use [`menu_event_receiver`] to get a reference to the [`MenuEventReceiver`]
|
||||
//! You can use [`MenuEvent::receiver`] to get a reference to the [`MenuEventReceiver`]
|
||||
//! which you can use to listen to events when a menu item is activated
|
||||
//! ```no_run
|
||||
//! # use muda::menu_event_receiver;
|
||||
//! # use muda::MenuEvent;
|
||||
//! #
|
||||
//! # let save_item: muda::MenuItem = unsafe { std::mem::zeroed() };
|
||||
//! if let Ok(event) = menu_event_receiver().try_recv() {
|
||||
//! if let Ok(event) = MenuEvent::receiver().try_recv() {
|
||||
//! match event.id {
|
||||
//! id if id == save_item.id() => {
|
||||
//! println!("Save menu item activated");
|
||||
|
@ -103,7 +103,7 @@
|
|||
//! See [`Menu::init_for_hwnd`] for more details
|
||||
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use once_cell::sync::Lazy;
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
|
||||
pub mod accelerator;
|
||||
mod check_menu_item;
|
||||
|
@ -192,7 +192,7 @@ pub trait ContextMenu {
|
|||
fn show_context_menu_for_hwnd(&self, hwnd: isize, x: f64, y: f64);
|
||||
|
||||
/// Attach the menu subclass handler to the given hwnd
|
||||
/// so you can recieve events from that window using [menu_event_receiver]
|
||||
/// so you can recieve events from that window using [MenuEvent::receiver]
|
||||
///
|
||||
/// This can be used along with [`ContextMenu::hpopupmenu`] when implementing a tray icon menu.
|
||||
#[cfg(target_os = "windows")]
|
||||
|
@ -231,11 +231,41 @@ pub struct MenuEvent {
|
|||
|
||||
/// A reciever that could be used to listen to menu events.
|
||||
pub type MenuEventReceiver = Receiver<MenuEvent>;
|
||||
type MenuEventHandler = Box<dyn Fn(MenuEvent) + Send + Sync + 'static>;
|
||||
|
||||
static MENU_CHANNEL: Lazy<(Sender<MenuEvent>, MenuEventReceiver)> = Lazy::new(unbounded);
|
||||
static MENU_EVENT_HANDLER: OnceCell<Option<MenuEventHandler>> = OnceCell::new();
|
||||
|
||||
/// Gets a reference to the event channel's [MenuEventReceiver]
|
||||
impl MenuEvent {
|
||||
/// Gets a reference to the event channel's [`MenuEventReceiver`]
|
||||
/// which can be used to listen for menu events.
|
||||
pub fn menu_event_receiver<'a>() -> &'a MenuEventReceiver {
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
/// This will not receive any events if [`MenuEvent::set_event_handler`] has been called with a `Some` value.
|
||||
pub fn receiver<'a>() -> &'a MenuEventReceiver {
|
||||
&MENU_CHANNEL.1
|
||||
}
|
||||
|
||||
/// Set a handler to be called for new events. Useful for implementing custom event sender.
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
/// Calling this function with a `Some` value,
|
||||
/// will not send new events to the channel associated with [`MenuEvent::receiver`]
|
||||
pub fn set_event_handler<F: Fn(MenuEvent) + Send + Sync + 'static>(f: Option<F>) {
|
||||
if let Some(f) = f {
|
||||
let _ = MENU_EVENT_HANDLER.set(Some(Box::new(f)));
|
||||
} else {
|
||||
let _ = MENU_EVENT_HANDLER.set(None);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn send(event: MenuEvent) {
|
||||
if let Some(handler) = MENU_EVENT_HANDLER.get_or_init(|| None) {
|
||||
handler(event);
|
||||
} else {
|
||||
let _ = MENU_CHANNEL.0.send(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
icon::Icon,
|
||||
predefined::PredfinedMenuItemType,
|
||||
util::{AddOp, Counter},
|
||||
MenuItemType,
|
||||
MenuEvent, MenuItemType,
|
||||
};
|
||||
use accelerator::{from_gtk_mnemonic, parse_accelerator, register_accelerator, to_gtk_mnemonic};
|
||||
use gtk::{prelude::*, Orientation};
|
||||
|
@ -826,7 +826,7 @@ impl MenuItem {
|
|||
|
||||
let id = self_.id;
|
||||
item.connect_activate(move |_| {
|
||||
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
|
||||
MenuEvent::send(crate::MenuEvent { id });
|
||||
});
|
||||
|
||||
if add_to_cache {
|
||||
|
@ -1069,7 +1069,7 @@ impl CheckMenuItem {
|
|||
|
||||
is_syncing_checked_state_c.store(false, Ordering::Release);
|
||||
|
||||
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
|
||||
MenuEvent::send(crate::MenuEvent { id });
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1188,7 +1188,7 @@ impl IconMenuItem {
|
|||
|
||||
let id = self_.id;
|
||||
item.connect_activate(move |_| {
|
||||
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
|
||||
MenuEvent::send(crate::MenuEvent { id });
|
||||
});
|
||||
|
||||
if add_to_cache {
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::{
|
|||
icon::Icon,
|
||||
predefined::PredfinedMenuItemType,
|
||||
util::{AddOp, Counter},
|
||||
MenuItemExt, MenuItemType,
|
||||
MenuEvent, MenuItemExt, MenuItemType,
|
||||
};
|
||||
|
||||
static COUNTER: Counter = Counter::new();
|
||||
|
@ -952,7 +952,7 @@ extern "C" fn fire_menu_item_click(this: &Object, _: Sel, _item: id) {
|
|||
(*item).set_checked(!(*item).is_checked());
|
||||
}
|
||||
|
||||
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
|
||||
MenuEvent::send(crate::MenuEvent { id });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
icon::Icon,
|
||||
predefined::PredfinedMenuItemType,
|
||||
util::{AddOp, Counter},
|
||||
MenuItemType,
|
||||
MenuEvent, MenuItemType,
|
||||
};
|
||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||
use util::{decode_wide, encode_wide, Accel};
|
||||
|
@ -1144,7 +1144,7 @@ website: {} {}
|
|||
}
|
||||
|
||||
if dispatch {
|
||||
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
|
||||
MenuEvent::send(crate::MenuEvent { id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue