mirror of
https://github.com/italicsjenga/muda.git
synced 2024-12-23 12:01:31 +11:00
refactor!: add MenuItemKind
enum (#79)
* refactor!: add `MenuItemKind` enum * remove as_any
This commit is contained in:
parent
22f2405bb9
commit
20c05ceae6
5
.changes/menu-item-kind.md
Normal file
5
.changes/menu-item-kind.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"muda": "minor"
|
||||
---
|
||||
|
||||
Removed `MenuItemType` enum and replaced with `MenuItemKind` enum. `Menu::items` and `Submenu::items` will now return `Vec<MenuItemKind>` instead of `Vec<Box<dyn MenuItemExt>>`
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
"muda": "patch"
|
||||
---
|
||||
|
||||
Add helper methods on `IsMenuItem` trait to make it easier to get the concrete type back.
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{accelerator::Accelerator, IsMenuItem, MenuItemType};
|
||||
use crate::{accelerator::Accelerator, IsMenuItem, MenuItemKind};
|
||||
|
||||
/// A check menu item inside a [`Menu`] or [`Submenu`]
|
||||
/// and usually contains a text and a check mark or a similar toggle
|
||||
|
@ -16,16 +16,8 @@ use crate::{accelerator::Accelerator, IsMenuItem, MenuItemType};
|
|||
pub struct CheckMenuItem(pub(crate) Rc<RefCell<crate::platform_impl::MenuChild>>);
|
||||
|
||||
unsafe impl IsMenuItem for CheckMenuItem {
|
||||
fn type_(&self) -> MenuItemType {
|
||||
MenuItemType::Check
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id()
|
||||
fn kind(&self) -> MenuItemKind {
|
||||
MenuItemKind::Check(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::{cell::RefCell, rc::Rc};
|
|||
use crate::{
|
||||
accelerator::Accelerator,
|
||||
icon::{Icon, NativeIcon},
|
||||
IsMenuItem, MenuItemType,
|
||||
IsMenuItem, MenuItemKind,
|
||||
};
|
||||
|
||||
/// An icon menu item inside a [`Menu`] or [`Submenu`]
|
||||
|
@ -19,16 +19,8 @@ use crate::{
|
|||
pub struct IconMenuItem(pub(crate) Rc<RefCell<crate::platform_impl::MenuChild>>);
|
||||
|
||||
unsafe impl IsMenuItem for IconMenuItem {
|
||||
fn type_(&self) -> MenuItemType {
|
||||
MenuItemType::Icon
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id()
|
||||
fn kind(&self) -> MenuItemKind {
|
||||
MenuItemKind::Icon(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{accelerator::Accelerator, IsMenuItem, MenuItemType};
|
||||
use crate::{accelerator::Accelerator, IsMenuItem, MenuItemKind};
|
||||
|
||||
/// A menu item inside a [`Menu`] or [`Submenu`] and contains only text.
|
||||
///
|
||||
|
@ -10,16 +10,8 @@ use crate::{accelerator::Accelerator, IsMenuItem, MenuItemType};
|
|||
pub struct MenuItem(pub(crate) Rc<RefCell<crate::platform_impl::MenuChild>>);
|
||||
|
||||
unsafe impl IsMenuItem for MenuItem {
|
||||
fn type_(&self) -> MenuItemType {
|
||||
MenuItemType::Normal
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id()
|
||||
fn kind(&self) -> MenuItemKind {
|
||||
MenuItemKind::MenuItem(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,24 +6,17 @@ use std::{cell::RefCell, rc::Rc};
|
|||
|
||||
use crate::{
|
||||
accelerator::{Accelerator, CMD_OR_CTRL},
|
||||
AboutMetadata, IsMenuItem, MenuItemType,
|
||||
AboutMetadata, IsMenuItem, MenuItemKind,
|
||||
};
|
||||
use keyboard_types::{Code, Modifiers};
|
||||
|
||||
/// A predefined (native) menu item which has a predfined behavior by the OS or by this crate.
|
||||
#[derive(Clone)]
|
||||
pub struct PredefinedMenuItem(pub(crate) Rc<RefCell<crate::platform_impl::MenuChild>>);
|
||||
|
||||
unsafe impl IsMenuItem for PredefinedMenuItem {
|
||||
fn type_(&self) -> MenuItemType {
|
||||
MenuItemType::Predefined
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id()
|
||||
fn kind(&self) -> MenuItemKind {
|
||||
MenuItemKind::Predefined(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +158,7 @@ impl PredefinedMenuItem {
|
|||
)))
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
pub(crate) fn id(&self) -> u32 {
|
||||
self.0.borrow().id()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuItemType, Position};
|
||||
use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuItemKind, Position};
|
||||
|
||||
/// A menu that can be added to a [`Menu`] or another [`Submenu`].
|
||||
///
|
||||
|
@ -13,16 +13,8 @@ use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuItemType, Position};
|
|||
pub struct Submenu(pub(crate) Rc<RefCell<crate::platform_impl::MenuChild>>);
|
||||
|
||||
unsafe impl IsMenuItem for Submenu {
|
||||
fn type_(&self) -> MenuItemType {
|
||||
MenuItemType::Submenu
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.id()
|
||||
fn kind(&self) -> MenuItemKind {
|
||||
MenuItemKind::Submenu(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +93,7 @@ impl Submenu {
|
|||
}
|
||||
|
||||
/// Returns a list of menu items that has been added to this submenu.
|
||||
pub fn items(&self) -> Vec<Box<dyn IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.0.borrow().items()
|
||||
}
|
||||
|
||||
|
|
200
src/lib.rs
200
src/lib.rs
|
@ -152,96 +152,136 @@ pub mod icon;
|
|||
|
||||
/// An enumeration of all available menu types, useful to match against
|
||||
/// the items return from [`Menu::items`] or [`Submenu::items`]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MenuItemType {
|
||||
#[derive(Clone)]
|
||||
pub enum MenuItemKind {
|
||||
MenuItem(MenuItem),
|
||||
Submenu(Submenu),
|
||||
Predefined(PredefinedMenuItem),
|
||||
Check(CheckMenuItem),
|
||||
Icon(IconMenuItem),
|
||||
}
|
||||
|
||||
impl MenuItemKind {
|
||||
/// Returns the id associated with this menu entry
|
||||
fn id(&self) -> u32 {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => i.id(),
|
||||
MenuItemKind::Submenu(i) => i.id(),
|
||||
MenuItemKind::Predefined(i) => i.id(),
|
||||
MenuItemKind::Check(i) => i.id(),
|
||||
MenuItemKind::Icon(i) => i.id(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`MenuItem`], and returns `None` if it wasn't.
|
||||
pub fn as_menuitem(&self) -> Option<&MenuItem> {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => Some(i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`MenuItem`], and panics if it wasn't.
|
||||
pub fn as_menuitem_unchecked(&self) -> &MenuItem {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => i,
|
||||
_ => panic!("Not a MenuItem"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`Submenu`], and returns `None` if it wasn't.
|
||||
pub fn as_submenu(&self) -> Option<&Submenu> {
|
||||
match self {
|
||||
MenuItemKind::Submenu(i) => Some(i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`Submenu`], and panics if it wasn't.
|
||||
pub fn as_submenu_unchecked(&self) -> &Submenu {
|
||||
match self {
|
||||
MenuItemKind::Submenu(i) => i,
|
||||
_ => panic!("Not a Submenu"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`PredefinedMenuItem`], and returns `None` if it wasn't.
|
||||
pub fn as_predefined_menuitem(&self) -> Option<&PredefinedMenuItem> {
|
||||
match self {
|
||||
MenuItemKind::Predefined(i) => Some(i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`PredefinedMenuItem`], and panics if it wasn't.
|
||||
pub fn as_predefined_menuitem_unchecked(&self) -> &PredefinedMenuItem {
|
||||
match self {
|
||||
MenuItemKind::Predefined(i) => i,
|
||||
_ => panic!("Not a PredefinedMenuItem"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`CheckMenuItem`], and returns `None` if it wasn't.
|
||||
pub fn as_check_menuitem(&self) -> Option<&CheckMenuItem> {
|
||||
match self {
|
||||
MenuItemKind::Check(i) => Some(i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`CheckMenuItem`], and panics if it wasn't.
|
||||
pub fn as_check_menuitem_unchecked(&self) -> &CheckMenuItem {
|
||||
match self {
|
||||
MenuItemKind::Check(i) => i,
|
||||
_ => panic!("Not a CheckMenuItem"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`IconMenuItem`], and returns `None` if it wasn't.
|
||||
pub fn as_icon_menuitem(&self) -> Option<&IconMenuItem> {
|
||||
match self {
|
||||
MenuItemKind::Icon(i) => Some(i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts this item to a [`IconMenuItem`], and panics if it wasn't.
|
||||
pub fn as_icon_menuitem_unchecked(&self) -> &IconMenuItem {
|
||||
match self {
|
||||
MenuItemKind::Icon(i) => i,
|
||||
_ => panic!("Not an IconMenuItem"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait that defines a generic item in a menu, which may be one of [`MenuItemKind`]
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait is ONLY meant to be implemented internally by the crate.
|
||||
pub unsafe trait IsMenuItem {
|
||||
fn kind(&self) -> MenuItemKind;
|
||||
|
||||
fn id(&self) -> u32 {
|
||||
self.kind().id()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
|
||||
pub(crate) enum MenuItemType {
|
||||
MenuItem,
|
||||
Submenu,
|
||||
Normal,
|
||||
Predefined,
|
||||
Check,
|
||||
Icon,
|
||||
}
|
||||
|
||||
impl Default for MenuItemType {
|
||||
fn default() -> Self {
|
||||
Self::Normal
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait that defines a generic item in a menu, which may be one of [MenuItemType]
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait is ONLY meant to be implemented internally.
|
||||
// TODO(amrbashir): first person to replace this trait with an enum while keeping `Menu.append_items`
|
||||
// taking mix of types (`MenuItem`, `CheckMenuItem`, `Submenu`...etc) in the same call, gets a cookie.
|
||||
pub unsafe trait IsMenuItem {
|
||||
/// Get the type of this menu entry
|
||||
fn type_(&self) -> MenuItemType;
|
||||
|
||||
/// Casts this menu entry to [`Any`](std::any::Any).
|
||||
///
|
||||
/// You can use this to get the concrete underlying type
|
||||
/// when calling [`Menu::items`] or [`Submenu::items`]
|
||||
/// by calling [`downcast_ref`](https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-1)
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use muda::{Submenu, MenuItem};
|
||||
/// let submenu = Submenu::new("Submenu", true);
|
||||
/// let item = MenuItem::new("Text", true, None);
|
||||
/// submenu.append(&item);
|
||||
/// // --snip--
|
||||
/// let item = &submenu.items()[0];
|
||||
/// let item = item.as_any().downcast_ref::<MenuItem>().unwrap();
|
||||
/// item.set_text("New text")
|
||||
/// ````
|
||||
fn as_any(&self) -> &(dyn std::any::Any + 'static);
|
||||
|
||||
/// Returns the id associated with this menu entry
|
||||
fn id(&self) -> u32;
|
||||
|
||||
/// Casts this item to a [`Submenu`], and returns `None` if it wasn't.
|
||||
fn as_submenu(&self) -> Option<&Submenu> {
|
||||
self.as_any().downcast_ref()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`Submenu`], and panics if it wasn't.
|
||||
fn as_submenu_unchecked(&self) -> &Submenu {
|
||||
self.as_any().downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`MenuItem`], and returns `None` if it wasn't.
|
||||
fn as_menuitem(&self) -> Option<&MenuItem> {
|
||||
self.as_any().downcast_ref()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`MenuItem`], and panics if it wasn't.
|
||||
fn as_menuitem_unchecked(&self) -> &MenuItem {
|
||||
self.as_any().downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`CheckMenuItem`], and returns `None` if it wasn't.
|
||||
fn as_check_menuitem(&self) -> Option<&CheckMenuItem> {
|
||||
self.as_any().downcast_ref()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`CheckMenuItem`], and panics if it wasn't.
|
||||
fn as_check_menuitem_unchecked(&self) -> &CheckMenuItem {
|
||||
self.as_any().downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`IconMenuItem`], and returns `None` if it wasn't.
|
||||
fn as_icon_menuitem(&self) -> Option<&IconMenuItem> {
|
||||
self.as_any().downcast_ref()
|
||||
}
|
||||
|
||||
/// Casts this item to a [`IconMenuItem`], and panics if it wasn't.
|
||||
fn as_icon_menuitem_unchecked(&self) -> &IconMenuItem {
|
||||
self.as_any().downcast_ref().unwrap()
|
||||
Self::MenuItem
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper trait with methods to help creating a context menu.
|
||||
pub trait ContextMenu {
|
||||
/// Get the popup [`HMENU`] for this menu.
|
||||
///
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{util::AddOp, ContextMenu, IsMenuItem, Position};
|
||||
use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuItemKind, Position};
|
||||
|
||||
/// A root menu that can be added to a Window on Windows and Linux
|
||||
/// and used as the app global menu on macOS.
|
||||
|
@ -117,7 +117,7 @@ impl Menu {
|
|||
}
|
||||
|
||||
/// Returns a list of menu items that has been added to this menu.
|
||||
pub fn items(&self) -> Vec<Box<dyn IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.0.borrow().items()
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
icon::{Icon, NativeIcon},
|
||||
items::*,
|
||||
util::{AddOp, Counter},
|
||||
MenuEvent, MenuItemType, Position,
|
||||
IsMenuItem, MenuEvent, MenuItemKind, MenuItemType, Position,
|
||||
};
|
||||
use accelerator::{from_gtk_mnemonic, parse_accelerator, to_gtk_mnemonic};
|
||||
use gtk::{prelude::*, Orientation};
|
||||
|
@ -29,9 +29,9 @@ macro_rules! return_if_predefined_item_not_supported {
|
|||
($item:tt) => {
|
||||
let child = $item.child();
|
||||
let child_ = child.borrow();
|
||||
match (&child_.type_, &child_.predefined_item_type) {
|
||||
match (&child_.item_type, &child_.predefined_item_type) {
|
||||
(
|
||||
crate::MenuItemType::Predefined,
|
||||
MenuItemType::Predefined,
|
||||
PredefinedMenuItemType::Separator
|
||||
| PredefinedMenuItemType::Copy
|
||||
| PredefinedMenuItemType::Cut
|
||||
|
@ -40,10 +40,10 @@ macro_rules! return_if_predefined_item_not_supported {
|
|||
| PredefinedMenuItemType::About(_),
|
||||
) => {}
|
||||
(
|
||||
crate::MenuItemType::Submenu
|
||||
| crate::MenuItemType::Normal
|
||||
| crate::MenuItemType::Check
|
||||
| crate::MenuItemType::Icon,
|
||||
MenuItemType::Submenu
|
||||
| MenuItemType::MenuItem
|
||||
| MenuItemType::Check
|
||||
| MenuItemType::Icon,
|
||||
_,
|
||||
) => {}
|
||||
_ => return Ok(()),
|
||||
|
@ -156,15 +156,12 @@ impl Menu {
|
|||
}
|
||||
};
|
||||
|
||||
if item.type_() == crate::MenuItemType::Submenu {
|
||||
let submenu = item.as_any().downcast_ref::<crate::Submenu>().unwrap();
|
||||
let gtk_menus = submenu.0.borrow().gtk_menus.clone();
|
||||
if let MenuItemKind::Submenu(i) = item.kind() {
|
||||
let gtk_menus = i.0.borrow().gtk_menus.clone();
|
||||
|
||||
for (menu_id, _) in gtk_menus {
|
||||
for item in submenu.items() {
|
||||
submenu
|
||||
.0
|
||||
.borrow_mut()
|
||||
for item in i.items() {
|
||||
i.0.borrow_mut()
|
||||
.remove_inner(item.as_ref(), false, Some(menu_id))?;
|
||||
}
|
||||
}
|
||||
|
@ -203,10 +200,10 @@ impl Menu {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn crate::IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -353,7 +350,7 @@ impl Menu {
|
|||
#[derive(Debug, Default)]
|
||||
pub struct MenuChild {
|
||||
// shared fields between submenus and menu items
|
||||
pub type_: MenuItemType,
|
||||
item_type: MenuItemType,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
id: u32,
|
||||
|
@ -389,7 +386,7 @@ impl MenuChild {
|
|||
enabled,
|
||||
accelerator,
|
||||
id: COUNTER.next(),
|
||||
type_: MenuItemType::Normal,
|
||||
item_type: MenuItemType::MenuItem,
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
..Default::default()
|
||||
}
|
||||
|
@ -401,7 +398,7 @@ impl MenuChild {
|
|||
enabled,
|
||||
id: COUNTER.next(),
|
||||
children: Some(Vec::new()),
|
||||
type_: MenuItemType::Submenu,
|
||||
item_type: MenuItemType::Submenu,
|
||||
gtk_menu: (COUNTER.next(), None),
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
gtk_menus: HashMap::new(),
|
||||
|
@ -415,7 +412,7 @@ impl MenuChild {
|
|||
enabled: true,
|
||||
accelerator: item_type.accelerator(),
|
||||
id: COUNTER.next(),
|
||||
type_: MenuItemType::Predefined,
|
||||
item_type: MenuItemType::Predefined,
|
||||
predefined_item_type: item_type,
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
..Default::default()
|
||||
|
@ -434,7 +431,7 @@ impl MenuChild {
|
|||
checked: Rc::new(AtomicBool::new(checked)),
|
||||
accelerator,
|
||||
id: COUNTER.next(),
|
||||
type_: MenuItemType::Check,
|
||||
item_type: MenuItemType::Check,
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
is_syncing_checked_state: Rc::new(AtomicBool::new(false)),
|
||||
..Default::default()
|
||||
|
@ -453,7 +450,7 @@ impl MenuChild {
|
|||
icon,
|
||||
accelerator,
|
||||
id: COUNTER.next(),
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
is_syncing_checked_state: Rc::new(AtomicBool::new(false)),
|
||||
..Default::default()
|
||||
|
@ -471,7 +468,7 @@ impl MenuChild {
|
|||
enabled,
|
||||
accelerator,
|
||||
id: COUNTER.next(),
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
gtk_menu_items: Rc::new(RefCell::new(HashMap::new())),
|
||||
is_syncing_checked_state: Rc::new(AtomicBool::new(false)),
|
||||
..Default::default()
|
||||
|
@ -481,6 +478,10 @@ impl MenuChild {
|
|||
|
||||
/// Shared methods
|
||||
impl MenuChild {
|
||||
pub(crate) fn item_type(&self) -> MenuItemType {
|
||||
self.item_type
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
@ -711,15 +712,12 @@ impl MenuChild {
|
|||
}
|
||||
};
|
||||
|
||||
if item.type_() == crate::MenuItemType::Submenu {
|
||||
let submenu = item.as_any().downcast_ref::<crate::Submenu>().unwrap();
|
||||
let gtk_menus = submenu.0.borrow().gtk_menus.clone();
|
||||
if let MenuItemKind::Submenu(i) = item.kind() {
|
||||
let gtk_menus = i.0.borrow().gtk_menus.clone();
|
||||
|
||||
for (menu_id, _) in gtk_menus {
|
||||
for item in submenu.items() {
|
||||
submenu
|
||||
.0
|
||||
.borrow_mut()
|
||||
for item in i.items() {
|
||||
i.0.borrow_mut()
|
||||
.remove_inner(item.as_ref(), false, Some(menu_id))?;
|
||||
}
|
||||
}
|
||||
|
@ -761,12 +759,12 @@ impl MenuChild {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn crate::IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -1133,53 +1131,46 @@ impl MenuChild {
|
|||
}
|
||||
}
|
||||
|
||||
impl dyn crate::IsMenuItem + '_ {
|
||||
impl MenuItemKind {
|
||||
fn make_gtk_menu_item(
|
||||
&self,
|
||||
menu_id: u32,
|
||||
accel_group: Option<>k::AccelGroup>,
|
||||
add_to_cache: bool,
|
||||
) -> crate::Result<gtk::MenuItem> {
|
||||
match self.type_() {
|
||||
MenuItemType::Submenu => self
|
||||
.as_any()
|
||||
.downcast_ref::<Submenu>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_gtk_item_for_submenu(menu_id, accel_group, add_to_cache),
|
||||
MenuItemType::Normal => self
|
||||
.as_any()
|
||||
.downcast_ref::<MenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_gtk_item_for_menu_item(menu_id, accel_group, add_to_cache),
|
||||
MenuItemType::Predefined => self
|
||||
.as_any()
|
||||
.downcast_ref::<PredefinedMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_gtk_item_for_predefined_menu_item(menu_id, accel_group, add_to_cache),
|
||||
MenuItemType::Check => self
|
||||
.as_any()
|
||||
.downcast_ref::<CheckMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_gtk_item_for_check_menu_item(menu_id, accel_group, add_to_cache),
|
||||
MenuItemType::Icon => self
|
||||
.as_any()
|
||||
.downcast_ref::<IconMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_gtk_item_for_icon_menu_item(menu_id, accel_group, add_to_cache),
|
||||
let mut child = self.child_mut();
|
||||
match child.item_type() {
|
||||
MenuItemType::Submenu => {
|
||||
child.create_gtk_item_for_submenu(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
MenuItemType::MenuItem => {
|
||||
child.create_gtk_item_for_menu_item(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
MenuItemType::Predefined => {
|
||||
child.create_gtk_item_for_predefined_menu_item(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
MenuItemType::Check => {
|
||||
child.create_gtk_item_for_check_menu_item(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
MenuItemType::Icon => {
|
||||
child.create_gtk_item_for_icon_menu_item(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn IsMenuItem + '_ {
|
||||
fn make_gtk_menu_item(
|
||||
&self,
|
||||
menu_id: u32,
|
||||
accel_group: Option<>k::AccelGroup>,
|
||||
add_to_cache: bool,
|
||||
) -> crate::Result<gtk::MenuItem> {
|
||||
self.kind()
|
||||
.make_gtk_menu_item(menu_id, accel_group, add_to_cache)
|
||||
}
|
||||
}
|
||||
|
||||
fn show_context_menu(
|
||||
gtk_menu: gtk::Menu,
|
||||
widget: &impl IsA<gtk::Widget>,
|
||||
|
|
|
@ -28,7 +28,7 @@ use crate::{
|
|||
icon::{Icon, NativeIcon},
|
||||
items::*,
|
||||
util::{AddOp, Counter},
|
||||
IsMenuItem, LogicalPosition, MenuEvent, MenuItemType, Position,
|
||||
IsMenuItem, LogicalPosition, MenuEvent, MenuItemKind, MenuItemType, Position,
|
||||
};
|
||||
|
||||
static COUNTER: Counter = Counter::new();
|
||||
|
@ -92,32 +92,16 @@ impl Menu {
|
|||
}
|
||||
|
||||
pub fn remove(&self, item: &dyn crate::IsMenuItem) -> crate::Result<()> {
|
||||
// get a list of instances of the specified NSMenuItem in this menu
|
||||
if let Some(ns_menu_items) = match item.type_() {
|
||||
MenuItemType::Submenu => {
|
||||
let submenu = item.as_any().downcast_ref::<Submenu>().unwrap();
|
||||
submenu.0.borrow_mut()
|
||||
}
|
||||
MenuItemType::Normal => {
|
||||
let menuitem = item.as_any().downcast_ref::<MenuItem>().unwrap();
|
||||
menuitem.0.borrow_mut()
|
||||
}
|
||||
MenuItemType::Predefined => {
|
||||
let menuitem = item.as_any().downcast_ref::<PredefinedMenuItem>().unwrap();
|
||||
menuitem.0.borrow_mut()
|
||||
}
|
||||
MenuItemType::Check => {
|
||||
let menuitem = item.as_any().downcast_ref::<CheckMenuItem>().unwrap();
|
||||
menuitem.0.borrow_mut()
|
||||
}
|
||||
MenuItemType::Icon => {
|
||||
let menuitem = item.as_any().downcast_ref::<IconMenuItem>().unwrap();
|
||||
menuitem.0.borrow_mut()
|
||||
}
|
||||
}
|
||||
.ns_menu_items
|
||||
.remove(&self.id)
|
||||
{
|
||||
// get a list of instances of the specified `NSMenuItem` in this menu
|
||||
let child = match item.kind() {
|
||||
MenuItemKind::Submenu(i) => i.0.clone(),
|
||||
MenuItemKind::MenuItem(i) => i.0.clone(),
|
||||
MenuItemKind::Predefined(i) => i.0.clone(),
|
||||
MenuItemKind::Check(i) => i.0.clone(),
|
||||
MenuItemKind::Icon(i) => i.0.clone(),
|
||||
};
|
||||
let mut child_ = child.borrow_mut();
|
||||
if let Some(ns_menu_items) = child_.ns_menu_items.remove(&self.id) {
|
||||
// remove each NSMenuItem from the NSMenu
|
||||
unsafe {
|
||||
for item in ns_menu_items {
|
||||
|
@ -137,11 +121,11 @@ impl Menu {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn crate::IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -166,7 +150,7 @@ impl Menu {
|
|||
#[derive(Debug)]
|
||||
pub struct MenuChild {
|
||||
// shared fields between submenus and menu items
|
||||
pub type_: MenuItemType,
|
||||
item_type: MenuItemType,
|
||||
id: u32,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
|
@ -195,7 +179,7 @@ pub struct MenuChild {
|
|||
impl Default for MenuChild {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
type_: Default::default(),
|
||||
item_type: Default::default(),
|
||||
id: Default::default(),
|
||||
text: Default::default(),
|
||||
enabled: Default::default(),
|
||||
|
@ -216,7 +200,7 @@ impl Default for MenuChild {
|
|||
impl MenuChild {
|
||||
pub fn new(text: &str, enabled: bool, accelerator: Option<Accelerator>) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Normal,
|
||||
item_type: MenuItemType::MenuItem,
|
||||
text: strip_mnemonic(text),
|
||||
enabled,
|
||||
id: COUNTER.next(),
|
||||
|
@ -227,7 +211,7 @@ impl MenuChild {
|
|||
|
||||
pub fn new_submenu(text: &str, enabled: bool) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Submenu,
|
||||
item_type: MenuItemType::Submenu,
|
||||
text: strip_mnemonic(text),
|
||||
enabled,
|
||||
children: Some(Vec::new()),
|
||||
|
@ -260,7 +244,7 @@ impl MenuChild {
|
|||
let accelerator = item_type.accelerator();
|
||||
|
||||
Self {
|
||||
type_: MenuItemType::Predefined,
|
||||
item_type: MenuItemType::Predefined,
|
||||
text,
|
||||
enabled: true,
|
||||
id: COUNTER.next(),
|
||||
|
@ -278,7 +262,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Check,
|
||||
item_type: MenuItemType::Check,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
id: COUNTER.next(),
|
||||
|
@ -295,7 +279,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
id: COUNTER.next(),
|
||||
|
@ -312,7 +296,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
id: COUNTER.next(),
|
||||
|
@ -325,6 +309,10 @@ impl MenuChild {
|
|||
|
||||
/// Shared methods
|
||||
impl MenuChild {
|
||||
pub(crate) fn item_type(&self) -> MenuItemType {
|
||||
self.item_type
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
self.id
|
||||
}
|
||||
|
@ -516,12 +504,12 @@ impl MenuChild {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn crate::IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -714,9 +702,9 @@ impl MenuChild {
|
|||
}
|
||||
|
||||
fn make_ns_item_for_menu(&mut self, menu_id: u32) -> crate::Result<*mut Object> {
|
||||
match self.type_ {
|
||||
match self.item_type {
|
||||
MenuItemType::Submenu => self.create_ns_item_for_submenu(menu_id),
|
||||
MenuItemType::Normal => self.create_ns_item_for_menu_item(menu_id),
|
||||
MenuItemType::MenuItem => self.create_ns_item_for_menu_item(menu_id),
|
||||
MenuItemType::Predefined => self.create_ns_item_for_predefined_menu_item(menu_id),
|
||||
MenuItemType::Check => self.create_ns_item_for_check_menu_item(menu_id),
|
||||
MenuItemType::Icon => self.create_ns_item_for_icon_menu_item(menu_id),
|
||||
|
@ -752,42 +740,15 @@ impl PredefinedMenuItemType {
|
|||
|
||||
impl dyn IsMenuItem + '_ {
|
||||
fn make_ns_item_for_menu(&self, menu_id: u32) -> crate::Result<*mut Object> {
|
||||
match self.type_() {
|
||||
MenuItemType::Submenu => self
|
||||
.as_any()
|
||||
.downcast_ref::<Submenu>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_ns_item_for_submenu(menu_id),
|
||||
MenuItemType::Normal => self
|
||||
.as_any()
|
||||
.downcast_ref::<MenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_ns_item_for_menu_item(menu_id),
|
||||
MenuItemType::Predefined => self
|
||||
.as_any()
|
||||
.downcast_ref::<PredefinedMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_ns_item_for_predefined_menu_item(menu_id),
|
||||
MenuItemType::Check => self
|
||||
.as_any()
|
||||
.downcast_ref::<CheckMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_ns_item_for_check_menu_item(menu_id),
|
||||
MenuItemType::Icon => self
|
||||
.as_any()
|
||||
.downcast_ref::<IconMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.borrow_mut()
|
||||
.create_ns_item_for_icon_menu_item(menu_id),
|
||||
match self.kind() {
|
||||
MenuItemKind::Submenu(i) => i.0.borrow_mut().create_ns_item_for_submenu(menu_id),
|
||||
MenuItemKind::MenuItem(i) => i.0.borrow_mut().create_ns_item_for_menu_item(menu_id),
|
||||
MenuItemKind::Predefined(i) => {
|
||||
i.0.borrow_mut()
|
||||
.create_ns_item_for_predefined_menu_item(menu_id)
|
||||
}
|
||||
MenuItemKind::Check(i) => i.0.borrow_mut().create_ns_item_for_check_menu_item(menu_id),
|
||||
MenuItemKind::Icon(i) => i.0.borrow_mut().create_ns_item_for_icon_menu_item(menu_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -895,7 +856,7 @@ extern "C" fn fire_menu_item_click(this: &Object, _: Sel, _item: id) {
|
|||
}
|
||||
}
|
||||
|
||||
if (*item).type_ == MenuItemType::Check {
|
||||
if (*item).item_type == MenuItemType::Check {
|
||||
(*item).set_checked(!(*item).is_checked());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,58 +12,70 @@ mod platform;
|
|||
#[path = "macos/mod.rs"]
|
||||
mod platform;
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::{
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use crate::{items::*, IsMenuItem, MenuItemType};
|
||||
use crate::{items::*, IsMenuItem, MenuItemKind, MenuItemType};
|
||||
|
||||
pub(crate) use self::platform::*;
|
||||
|
||||
impl dyn IsMenuItem + '_ {
|
||||
fn child(&self) -> Rc<RefCell<MenuChild>> {
|
||||
match self.type_() {
|
||||
MenuItemType::Submenu => self
|
||||
.as_any()
|
||||
.downcast_ref::<crate::Submenu>()
|
||||
.unwrap()
|
||||
.0
|
||||
.clone(),
|
||||
MenuItemType::Normal => self
|
||||
.as_any()
|
||||
.downcast_ref::<crate::MenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.clone(),
|
||||
MenuItemType::Predefined => self
|
||||
.as_any()
|
||||
.downcast_ref::<crate::PredefinedMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.clone(),
|
||||
MenuItemType::Check => self
|
||||
.as_any()
|
||||
.downcast_ref::<crate::CheckMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.clone(),
|
||||
MenuItemType::Icon => self
|
||||
.as_any()
|
||||
.downcast_ref::<crate::IconMenuItem>()
|
||||
.unwrap()
|
||||
.0
|
||||
.clone(),
|
||||
match self.kind() {
|
||||
MenuItemKind::MenuItem(i) => i.0,
|
||||
MenuItemKind::Submenu(i) => i.0,
|
||||
MenuItemKind::Predefined(i) => i.0,
|
||||
MenuItemKind::Check(i) => i.0,
|
||||
MenuItemKind::Icon(i) => i.0,
|
||||
}
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal utilities
|
||||
impl MenuChild {
|
||||
fn boxed(&self, c: Rc<RefCell<MenuChild>>) -> Box<dyn IsMenuItem> {
|
||||
match self.type_ {
|
||||
MenuItemType::Submenu => Box::new(Submenu(c)),
|
||||
MenuItemType::Normal => Box::new(MenuItem(c)),
|
||||
MenuItemType::Predefined => Box::new(PredefinedMenuItem(c)),
|
||||
MenuItemType::Check => Box::new(CheckMenuItem(c)),
|
||||
MenuItemType::Icon => Box::new(IconMenuItem(c)),
|
||||
fn kind(&self, c: Rc<RefCell<MenuChild>>) -> MenuItemKind {
|
||||
match self.item_type() {
|
||||
MenuItemType::Submenu => MenuItemKind::Submenu(Submenu(c)),
|
||||
MenuItemType::MenuItem => MenuItemKind::MenuItem(MenuItem(c)),
|
||||
MenuItemType::Predefined => MenuItemKind::Predefined(PredefinedMenuItem(c)),
|
||||
MenuItemType::Check => MenuItemKind::Check(CheckMenuItem(c)),
|
||||
MenuItemType::Icon => MenuItemKind::Icon(IconMenuItem(c)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl MenuItemKind {
|
||||
pub(crate) fn as_ref(&self) -> &dyn IsMenuItem {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => i,
|
||||
MenuItemKind::Submenu(i) => i,
|
||||
MenuItemKind::Predefined(i) => i,
|
||||
MenuItemKind::Check(i) => i,
|
||||
MenuItemKind::Icon(i) => i,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn child(&self) -> Ref<MenuChild> {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => i.0.borrow(),
|
||||
MenuItemKind::Submenu(i) => i.0.borrow(),
|
||||
MenuItemKind::Predefined(i) => i.0.borrow(),
|
||||
MenuItemKind::Check(i) => i.0.borrow(),
|
||||
MenuItemKind::Icon(i) => i.0.borrow(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn child_mut(&self) -> RefMut<MenuChild> {
|
||||
match self {
|
||||
MenuItemKind::MenuItem(i) => i.0.borrow_mut(),
|
||||
MenuItemKind::Submenu(i) => i.0.borrow_mut(),
|
||||
MenuItemKind::Predefined(i) => i.0.borrow_mut(),
|
||||
MenuItemKind::Check(i) => i.0.borrow_mut(),
|
||||
MenuItemKind::Icon(i) => i.0.borrow_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ use crate::{
|
|||
icon::{Icon, NativeIcon},
|
||||
items::PredefinedMenuItemType,
|
||||
util::{AddOp, Counter},
|
||||
AboutMetadata, CheckMenuItem, IconMenuItem, IsMenuItem, MenuEvent, MenuItem, MenuItemType,
|
||||
Position, PredefinedMenuItem, Submenu,
|
||||
AboutMetadata, IsMenuItem, MenuEvent, MenuItemKind, MenuItemType, Position,
|
||||
};
|
||||
use std::{
|
||||
cell::{RefCell, RefMut},
|
||||
|
@ -49,19 +48,18 @@ type AccelWrapper = (HACCEL, HashMap<u32, Accel>);
|
|||
macro_rules! inner_menu_child_and_flags {
|
||||
($item:ident) => {{
|
||||
let mut flags = 0;
|
||||
let child = match $item.type_() {
|
||||
MenuItemType::Submenu => {
|
||||
let child = match $item.kind() {
|
||||
MenuItemKind::Submenu(i) => {
|
||||
flags |= MF_POPUP;
|
||||
&$item.as_any().downcast_ref::<Submenu>().unwrap().0
|
||||
i.0.clone()
|
||||
}
|
||||
MenuItemType::Normal => {
|
||||
MenuItemKind::MenuItem(i) => {
|
||||
flags |= MF_STRING;
|
||||
&$item.as_any().downcast_ref::<MenuItem>().unwrap().0
|
||||
i.0.clone()
|
||||
}
|
||||
|
||||
MenuItemType::Predefined => {
|
||||
let item = $item.as_any().downcast_ref::<PredefinedMenuItem>().unwrap();
|
||||
let child = &item.0;
|
||||
MenuItemKind::Predefined(i) => {
|
||||
let child = i.0.clone();
|
||||
let child_ = child.borrow();
|
||||
match child_.predefined_item_type {
|
||||
PredefinedMenuItemType::None => return Ok(()),
|
||||
|
@ -72,24 +70,24 @@ macro_rules! inner_menu_child_and_flags {
|
|||
flags |= MF_STRING;
|
||||
}
|
||||
}
|
||||
drop(child_);
|
||||
child
|
||||
}
|
||||
MenuItemType::Check => {
|
||||
let item = $item.as_any().downcast_ref::<CheckMenuItem>().unwrap();
|
||||
let child = &item.0;
|
||||
MenuItemKind::Check(i) => {
|
||||
let child = i.0.clone();
|
||||
flags |= MF_STRING;
|
||||
if child.borrow().checked {
|
||||
flags |= MF_CHECKED;
|
||||
}
|
||||
child
|
||||
}
|
||||
MenuItemType::Icon => {
|
||||
MenuItemKind::Icon(i) => {
|
||||
flags |= MF_STRING;
|
||||
&$item.as_any().downcast_ref::<IconMenuItem>().unwrap().0
|
||||
i.0.clone()
|
||||
}
|
||||
};
|
||||
|
||||
(child.clone(), flags)
|
||||
(child, flags)
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -184,7 +182,7 @@ impl Menu {
|
|||
{
|
||||
let child_ = child.borrow();
|
||||
|
||||
if child_.type_ == MenuItemType::Icon {
|
||||
if child_.item_type() == MenuItemType::Icon {
|
||||
let hbitmap = child_
|
||||
.icon
|
||||
.as_ref()
|
||||
|
@ -253,10 +251,10 @@ impl Menu {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -370,7 +368,7 @@ impl Menu {
|
|||
#[derive(Debug, Default)]
|
||||
pub(crate) struct MenuChild {
|
||||
// shared fields between submenus and menu items
|
||||
pub type_: MenuItemType,
|
||||
item_type: MenuItemType,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
parents_hemnu: Vec<HMENU>,
|
||||
|
@ -399,7 +397,7 @@ pub(crate) struct MenuChild {
|
|||
impl MenuChild {
|
||||
pub fn new(text: &str, enabled: bool, accelerator: Option<Accelerator>) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Normal,
|
||||
item_type: MenuItemType::MenuItem,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -412,7 +410,7 @@ impl MenuChild {
|
|||
|
||||
pub fn new_submenu(text: &str, enabled: bool) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Submenu,
|
||||
item_type: MenuItemType::Submenu,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -426,7 +424,7 @@ impl MenuChild {
|
|||
|
||||
pub fn new_predefined(item_type: PredefinedMenuItemType, text: Option<String>) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Predefined,
|
||||
item_type: MenuItemType::Predefined,
|
||||
text: text.unwrap_or_else(|| item_type.text().to_string()),
|
||||
enabled: true,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -445,7 +443,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Check,
|
||||
item_type: MenuItemType::Check,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -464,7 +462,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -483,7 +481,7 @@ impl MenuChild {
|
|||
accelerator: Option<Accelerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
type_: MenuItemType::Icon,
|
||||
item_type: MenuItemType::Icon,
|
||||
text: text.to_string(),
|
||||
enabled,
|
||||
parents_hemnu: Vec::new(),
|
||||
|
@ -497,8 +495,12 @@ impl MenuChild {
|
|||
|
||||
/// Shared methods
|
||||
impl MenuChild {
|
||||
pub fn item_type(&self) -> MenuItemType {
|
||||
self.item_type
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u32 {
|
||||
match self.type_ {
|
||||
match self.item_type() {
|
||||
MenuItemType::Submenu => self.hmenu as u32,
|
||||
_ => self.id,
|
||||
}
|
||||
|
@ -705,7 +707,7 @@ impl MenuChild {
|
|||
{
|
||||
let child_ = child.borrow();
|
||||
|
||||
if child_.type_ == MenuItemType::Icon {
|
||||
if child_.item_type() == MenuItemType::Icon {
|
||||
let hbitmap = child_
|
||||
.icon
|
||||
.as_ref()
|
||||
|
@ -771,12 +773,12 @@ impl MenuChild {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Vec<Box<dyn IsMenuItem>> {
|
||||
pub fn items(&self) -> Vec<MenuItemKind> {
|
||||
self.children
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|c| c.borrow().boxed(c.clone()))
|
||||
.map(|c| c.borrow().kind(c.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -818,7 +820,7 @@ fn find_by_id(id: u32, children: &Vec<Rc<RefCell<MenuChild>>>) -> Option<Rc<RefC
|
|||
return Some(i.clone());
|
||||
}
|
||||
|
||||
if item.type_ == MenuItemType::Submenu {
|
||||
if item.item_type() == MenuItemType::Submenu {
|
||||
if let Some(child) = item.find_by_id(id) {
|
||||
return Some(child);
|
||||
}
|
||||
|
@ -933,11 +935,11 @@ unsafe extern "system" fn menu_subclass_proc(
|
|||
{
|
||||
let mut item = item.borrow_mut();
|
||||
|
||||
if item.type_ == MenuItemType::Predefined {
|
||||
if item.item_type() == MenuItemType::Predefined {
|
||||
dispatch = false;
|
||||
}
|
||||
|
||||
match item.type_ {
|
||||
match item.item_type() {
|
||||
MenuItemType::Check => {
|
||||
let checked = !item.checked;
|
||||
item.set_checked(checked);
|
||||
|
|
|
@ -134,6 +134,7 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 {
|
|||
// We are on Windows 10 Anniversary Update (1607) or later.
|
||||
match GetDpiForWindow(hwnd) {
|
||||
0 => BASE_DPI, // 0 is returned if hwnd is invalid
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
dpi => dpi as u32,
|
||||
}
|
||||
} else if let Some(GetDpiForMonitor) = *GET_DPI_FOR_MONITOR {
|
||||
|
@ -145,6 +146,7 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 {
|
|||
|
||||
let mut dpi_x = 0;
|
||||
let mut dpi_y = 0;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
if GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y) == S_OK {
|
||||
dpi_x as u32
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue