use crate::{
runtime::{
menu::{MenuHash, MenuId, MenuIdRef, MenuUpdate},
Dispatch,
},
Runtime,
};
use tauri_macros::default_runtime;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
#[derive(Debug, Clone)]
pub struct MenuEvent {
pub(crate) menu_item_id: MenuId,
}
impl MenuEvent {
pub fn menu_item_id(&self) -> MenuIdRef<'_> {
&self.menu_item_id
}
}
#[default_runtime(crate::Wry, wry)]
#[derive(Debug)]
pub struct MenuHandle<R: Runtime> {
pub(crate) ids: Arc<Mutex<HashMap<MenuHash, MenuId>>>,
pub(crate) dispatcher: R::Dispatcher,
}
impl<R: Runtime> Clone for MenuHandle<R> {
fn clone(&self) -> Self {
Self {
ids: self.ids.clone(),
dispatcher: self.dispatcher.clone(),
}
}
}
#[default_runtime(crate::Wry, wry)]
#[derive(Debug)]
pub struct MenuItemHandle<R: Runtime> {
id: u16,
dispatcher: R::Dispatcher,
}
impl<R: Runtime> Clone for MenuItemHandle<R> {
fn clone(&self) -> Self {
Self {
id: self.id,
dispatcher: self.dispatcher.clone(),
}
}
}
impl<R: Runtime> MenuHandle<R> {
pub fn get_item(&self, id: MenuIdRef<'_>) -> MenuItemHandle<R> {
let ids = self.ids.lock().unwrap();
let iter = ids.iter();
for (raw, item_id) in iter {
if item_id == id {
return MenuItemHandle {
id: *raw,
dispatcher: self.dispatcher.clone(),
};
}
}
panic!("item id not found")
}
pub fn try_get_item(&self, id: MenuIdRef<'_>) -> Option<MenuItemHandle<R>> {
self
.ids
.lock()
.unwrap()
.iter()
.find(|i| i.1 == id)
.map(|i| MenuItemHandle {
id: *i.0,
dispatcher: self.dispatcher.clone(),
})
}
pub fn show(&self) -> crate::Result<()> {
self.dispatcher.show_menu().map_err(Into::into)
}
pub fn hide(&self) -> crate::Result<()> {
self.dispatcher.hide_menu().map_err(Into::into)
}
pub fn is_visible(&self) -> crate::Result<bool> {
self.dispatcher.is_menu_visible().map_err(Into::into)
}
pub fn toggle(&self) -> crate::Result<()> {
if self.is_visible()? {
self.hide()
} else {
self.show()
}
}
}
impl<R: Runtime> MenuItemHandle<R> {
pub fn set_enabled(&self, enabled: bool) -> crate::Result<()> {
self
.dispatcher
.update_menu_item(self.id, MenuUpdate::SetEnabled(enabled))
.map_err(Into::into)
}
pub fn set_title<S: Into<String>>(&self, title: S) -> crate::Result<()> {
self
.dispatcher
.update_menu_item(self.id, MenuUpdate::SetTitle(title.into()))
.map_err(Into::into)
}
pub fn set_selected(&self, selected: bool) -> crate::Result<()> {
self
.dispatcher
.update_menu_item(self.id, MenuUpdate::SetSelected(selected))
.map_err(Into::into)
}
#[cfg(target_os = "macos")]
#[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
pub fn set_native_image(&self, image: crate::NativeImage) -> crate::Result<()> {
self
.dispatcher
.update_menu_item(self.id, MenuUpdate::SetNativeImage(image))
.map_err(Into::into)
}
}