Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: allow changing the menu event sender #35

Merged
merged 4 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/event_handler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"muda": "patch"
---

Add `MenuEvent::set_event_handler` to set a handler for new menu events.
5 changes: 5 additions & 0 deletions .changes/rm-menu-event-receiver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"muda": "minor"
---

**Breaking change** Remove `menu_event_receiver` function, use `MenuEvent::receiver` instead.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 2 additions & 2 deletions examples/tao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions examples/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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;
Expand Down
48 changes: 39 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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;
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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]
/// which can be used to listen for menu events.
pub fn menu_event_receiver<'a>() -> &'a MenuEventReceiver {
&MENU_CHANNEL.1
impl MenuEvent {
/// Gets a reference to the event channel's [`MenuEventReceiver`]
/// which can be used to listen for menu events.
///
/// ## 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);
}
}
}
8 changes: 4 additions & 4 deletions src/platform_impl/gtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 });
}
});

Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/macos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
icon::Icon,
predefined::PredfinedMenuItemType,
util::{AddOp, Counter},
MenuItemExt, MenuItemType,
MenuEvent, MenuItemExt, MenuItemType,
};

static COUNTER: Counter = Counter::new();
Expand Down Expand Up @@ -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 });
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -1144,7 +1144,7 @@ website: {} {}
}

if dispatch {
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
MenuEvent::send(crate::MenuEvent { id });
}
}
}
Expand Down