From 421b00f597bd9c52cc035c84357fc848c75e02fc Mon Sep 17 00:00:00 2001 From: "Ngo Iok Ui (Wu Yu Wei)" Date: Sat, 11 Jun 2022 20:35:33 +0800 Subject: [PATCH] refactor(linux): combine `r#type` and `native_*` into sum type --- src/lib.rs | 4 +- src/platform_impl/linux/mod.rs | 163 ++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 77 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0aee1b0..369734a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -323,7 +323,7 @@ impl TextMenuItem { } #[non_exhaustive] -#[derive(Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] pub enum NativeMenuItem { /// A native “About” menu item. /// @@ -427,7 +427,7 @@ pub enum NativeMenuItem { /// ## Platform-specific /// /// - **macOS**: The metadata is ignored. -#[derive(Debug, Clone, Default)] +#[derive(PartialEq, Eq, Debug, Clone, Default)] pub struct AboutMetadata { /// The application name. pub version: Option, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 26a0cdf..cae75e8 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -8,34 +8,25 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc}; static COUNTER: Counter = Counter::new(); /// Generic shared type describing a menu entry. It can be one of [`MenuEntryType`] -#[derive(Debug, Default)] +#[derive(Debug)] struct MenuEntry { label: String, enabled: bool, r#type: MenuEntryType, item_id: Option, accelerator: Option, - native_menu_item: Option, - // NOTE(amrbashir): because gtk doesn't allow using the same [`gtk::MenuItem`] - // multiple times, and thus can't be used in multiple windows, each entry - // keeps a vector of a [`gtk::MenuItem`] or a tuple of [`gtk::MenuItem`] and [`gtk::Menu`] if its a menu - // and push to it every time [`Menu::init_for_gtk_window`] is called. - native_items: Option>, - native_menus: Option>, entries: Option>>>, } #[derive(PartialEq, Eq, Debug)] enum MenuEntryType { - Submenu, - Text, - Native, -} - -impl Default for MenuEntryType { - fn default() -> Self { - MenuEntryType::Text - } + // NOTE(amrbashir): because gtk doesn't allow using the same [`gtk::MenuItem`] + // multiple times, and thus can't be used in multiple windows, each entry + // keeps a vector of a [`gtk::MenuItem`] or a tuple of [`gtk::MenuItem`] and [`gtk::Menu`] if its a menu + // and push to it every time [`Menu::init_for_gtk_window`] is called. + Submenu(Vec<(gtk::MenuItem, gtk::Menu)>), + Text(Vec), + Native(NativeMenuItem), } struct InnerMenu { @@ -67,9 +58,9 @@ impl Menu { label: label.clone(), enabled, entries: Some(Vec::new()), - r#type: MenuEntryType::Submenu, - native_menus: Some(Vec::new()), - ..Default::default() + r#type: MenuEntryType::Submenu(Vec::new()), + item_id: Default::default(), + accelerator: None, })); let mut inner = self.0.borrow_mut(); @@ -77,12 +68,10 @@ impl Menu { if let Some(menu_bar) = menu_bar { let (item, submenu) = create_gtk_submenu(&label, enabled); menu_bar.append(&item); - entry - .borrow_mut() - .native_menus - .as_mut() - .unwrap() - .push((item, submenu)); + let mut native_menus = entry.borrow_mut(); + if let MenuEntryType::Submenu(m) = &mut native_menus.r#type { + m.push((item, submenu)); + } } } @@ -199,8 +188,10 @@ impl Submenu { pub fn set_label(&mut self, label: impl AsRef) { let label = label.as_ref().to_string(); let mut entry = self.0.borrow_mut(); - for (item, _) in entry.native_menus.as_ref().unwrap() { - item.set_label(&to_gtk_menemenoic(&label)); + if let MenuEntryType::Submenu(native_menus) = &mut entry.r#type { + for (item, _) in native_menus { + item.set_label(&to_gtk_menemenoic(&label)); + } } entry.label = label; } @@ -212,8 +203,10 @@ impl Submenu { pub fn set_enabled(&mut self, enabled: bool) { let mut entry = self.0.borrow_mut(); entry.enabled = true; - for (item, _) in entry.native_menus.as_ref().unwrap() { - item.set_sensitive(enabled); + if let MenuEntryType::Submenu(native_menus) = &mut entry.r#type { + for (item, _) in native_menus { + item.set_sensitive(enabled); + } } } @@ -224,21 +217,20 @@ impl Submenu { label: label.clone(), enabled, entries: Some(Vec::new()), - r#type: MenuEntryType::Submenu, - native_menus: Some(Vec::new()), - ..Default::default() + r#type: MenuEntryType::Submenu(Vec::new()), + item_id: Default::default(), + accelerator: None, })); let mut inner = self.0.borrow_mut(); - for (_, menu) in inner.native_menus.as_ref().unwrap() { - let (item, submenu) = create_gtk_submenu(&label, enabled); - menu.append(&item); - entry - .borrow_mut() - .native_menus - .as_mut() - .unwrap() - .push((item, submenu)); + if let MenuEntryType::Submenu(native_menus) = &mut inner.r#type { + for (_, menu) in native_menus { + let (item, submenu) = create_gtk_submenu(&label, enabled); + menu.append(&item); + if let MenuEntryType::Submenu(menus) = &mut entry.borrow_mut().r#type { + menus.push((item, submenu)); + } + } } inner.entries.as_mut().unwrap().push(entry.clone()); @@ -257,25 +249,28 @@ impl Submenu { let entry = Rc::new(RefCell::new(MenuEntry { label: label.clone(), enabled, - r#type: MenuEntryType::Text, + r#type: MenuEntryType::Text(Vec::new()), item_id: Some(id), accelerator: accelerator.map(|s| s.to_string()), - native_items: Some(Vec::new()), - ..Default::default() + entries: None, })); let mut inner = self.0.borrow_mut(); - for (_, menu) in inner.native_menus.as_ref().unwrap() { - let item = create_gtk_text_menu_item( - &label, - enabled, - &accelerator.map(|s| s.to_string()), - id, - &*self.1, - ); - menu.append(&item); - entry.borrow_mut().native_items.as_mut().unwrap().push(item); + if let MenuEntryType::Submenu(native_menus) = &mut inner.r#type { + for (_, menu) in native_menus { + let item = create_gtk_text_menu_item( + &label, + enabled, + &accelerator.map(|s| s.to_string()), + id, + &*self.1, + ); + menu.append(&item); + if let MenuEntryType::Text(native_items) = &mut entry.borrow_mut().r#type { + native_items.push(item); + } + } } inner.entries.as_mut().unwrap().push(entry.clone()); @@ -285,14 +280,19 @@ impl Submenu { pub fn add_native_item(&mut self, item: NativeMenuItem) { let mut inner = self.0.borrow_mut(); - for (_, menu) in inner.native_menus.as_ref().unwrap() { - item.add_to_gtk_menu(menu); + if let MenuEntryType::Submenu(native_menus) = &mut inner.r#type { + for (_, menu) in native_menus { + item.add_to_gtk_menu(menu); + } } let entry = Rc::new(RefCell::new(MenuEntry { - r#type: MenuEntryType::Native, - native_menu_item: Some(item), - ..Default::default() + r#type: MenuEntryType::Native(item), + label: Default::default(), + enabled: Default::default(), + item_id: Default::default(), + accelerator: Default::default(), + entries: Default::default(), })); inner.entries.as_mut().unwrap().push(entry); } @@ -309,8 +309,10 @@ impl TextMenuItem { pub fn set_label(&mut self, label: impl AsRef) { let label = label.as_ref().to_string(); let mut entry = self.0.borrow_mut(); - for item in entry.native_items.as_ref().unwrap() { - item.set_label(&to_gtk_menemenoic(&label)); + if let MenuEntryType::Text(native_items) = &mut entry.r#type { + for item in native_items { + item.set_label(&to_gtk_menemenoic(&label)); + } } entry.label = label; } @@ -321,8 +323,10 @@ impl TextMenuItem { pub fn set_enabled(&mut self, enabled: bool) { let mut entry = self.0.borrow_mut(); - for item in entry.native_items.as_ref().unwrap() { - item.set_sensitive(enabled); + if let MenuEntryType::Text(native_items) = &mut entry.r#type { + for item in native_items { + item.set_sensitive(enabled); + } } entry.enabled = enabled; } @@ -339,14 +343,14 @@ fn add_entries_to_menu>( ) { for entry in entries { let mut entry = entry.borrow_mut(); - match entry.r#type { - MenuEntryType::Submenu => { + let (item, submenu) = match &entry.r#type { + MenuEntryType::Submenu(_) => { let (item, submenu) = create_gtk_submenu(&entry.label, entry.enabled); gtk_menu.append(&item); add_entries_to_menu(&submenu, entry.entries.as_ref().unwrap(), accel_group); - entry.native_menus.as_mut().unwrap().push((item, submenu)); + (Some(item), Some(submenu)) } - MenuEntryType::Text => { + MenuEntryType::Text(_) => { let item = create_gtk_text_menu_item( &entry.label, entry.enabled, @@ -355,14 +359,23 @@ fn add_entries_to_menu>( accel_group, ); gtk_menu.append(&item); - entry.native_items.as_mut().unwrap().push(item); + (Some(item), None) } - MenuEntryType::Native => entry - .native_menu_item - .as_ref() - .unwrap() - .add_to_gtk_menu(gtk_menu), - } + MenuEntryType::Native(native_menu_item) => { + native_menu_item.add_to_gtk_menu(gtk_menu); + (None, None) + } + }; + + match &mut entry.r#type { + MenuEntryType::Submenu(native_menus) => { + native_menus.push((item.unwrap(), submenu.unwrap())); + } + MenuEntryType::Text(native_items) => { + native_items.push(item.unwrap()); + } + MenuEntryType::Native(_) => {} + }; } }