refactor(linux): use Rc<RefCell> instead of Arc<Mutex>

This commit is contained in:
amrbashir 2022-06-06 14:42:35 +02:00
parent 6cb2ce1c7a
commit 68f16f15a3
No known key found for this signature in database
GPG key ID: BBD7A47A2003FF33
2 changed files with 55 additions and 39 deletions

View file

@ -25,7 +25,6 @@ features = [
] ]
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
parking_lot = "0.12"
gtk = "0.15" gtk = "0.15"
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]

View file

@ -2,8 +2,7 @@
use crate::util::Counter; use crate::util::Counter;
use gtk::{prelude::*, Orientation}; use gtk::{prelude::*, Orientation};
use parking_lot::Mutex; use std::{cell::RefCell, rc::Rc};
use std::{rc::Rc, sync::Arc};
static COUNTER: Counter = Counter::new(); static COUNTER: Counter = Counter::new();
@ -22,13 +21,13 @@ struct MenuEntry {
// multiple times, and thus can't be used in multiple windows, each entry // 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` // keeps a vector of a `gtk::MenuItem` or a tuple of `gtk::MenuItem` and `gtk::Menu`
// and push to it every time `Menu::init_for_gtk_window` is called. // and push to it every time `Menu::init_for_gtk_window` is called.
item_gtk_items: Option<Arc<Mutex<Vec<gtk::MenuItem>>>>, item_gtk_items: Option<Rc<RefCell<Vec<gtk::MenuItem>>>>,
menu_gtk_items: Option<Arc<Mutex<Vec<(gtk::MenuItem, gtk::Menu)>>>>, menu_gtk_items: Option<Rc<RefCell<Vec<(gtk::MenuItem, gtk::Menu)>>>>,
entries: Option<Vec<Arc<Mutex<MenuEntry>>>>, entries: Option<Vec<Rc<RefCell<MenuEntry>>>>,
} }
struct InnerMenu { struct InnerMenu {
entries: Vec<Arc<Mutex<MenuEntry>>>, entries: Vec<Rc<RefCell<MenuEntry>>>,
// NOTE(amrbashir): because gtk doesn't allow using the same `gtk::MenuBar` and `gtk::Box` // NOTE(amrbashir): because gtk doesn't allow using the same `gtk::MenuBar` and `gtk::Box`
// multiple times, and thus can't be used in multiple windows, entry // multiple times, and thus can't be used in multiple windows, entry
// keeps a vector of a tuple of `gtk::MenuBar` and `gtk::Box` // keeps a vector of a tuple of `gtk::MenuBar` and `gtk::Box`
@ -36,11 +35,11 @@ struct InnerMenu {
gtk_items: Vec<(gtk::MenuBar, Rc<gtk::Box>)>, gtk_items: Vec<(gtk::MenuBar, Rc<gtk::Box>)>,
} }
pub struct Menu(Arc<Mutex<InnerMenu>>); pub struct Menu(Rc<RefCell<InnerMenu>>);
impl Menu { impl Menu {
pub fn new() -> Self { pub fn new() -> Self {
Self(Arc::new(Mutex::new(InnerMenu { Self(Rc::new(RefCell::new(InnerMenu {
entries: Vec::new(), entries: Vec::new(),
gtk_items: Vec::new(), gtk_items: Vec::new(),
}))) })))
@ -48,16 +47,16 @@ impl Menu {
pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu { pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu {
let label = label.as_ref().to_string(); let label = label.as_ref().to_string();
let entry = Arc::new(Mutex::new(MenuEntry { let entry = Rc::new(RefCell::new(MenuEntry {
label: label.clone(), label: label.clone(),
enabled, enabled,
entries: Some(Vec::new()), entries: Some(Vec::new()),
r#type: MenuEntryType::Submenu, r#type: MenuEntryType::Submenu,
item_id: None, item_id: None,
menu_gtk_items: Some(Arc::new(Mutex::new(Vec::new()))), menu_gtk_items: Some(Rc::new(RefCell::new(Vec::new()))),
item_gtk_items: None, item_gtk_items: None,
})); }));
self.0.lock().entries.push(entry.clone()); self.0.borrow_mut().entries.push(entry.clone());
Submenu(entry) Submenu(entry)
} }
@ -66,7 +65,7 @@ impl Menu {
W: IsA<gtk::Container>, W: IsA<gtk::Container>,
{ {
let menu_bar = gtk::MenuBar::new(); let menu_bar = gtk::MenuBar::new();
add_entries_to_menu(&menu_bar, &self.0.lock().entries); add_entries_to_menu(&menu_bar, &self.0.borrow().entries);
let vbox = gtk::Box::new(Orientation::Vertical, 0); let vbox = gtk::Box::new(Orientation::Vertical, 0);
vbox.pack_start(&menu_bar, false, false, 0); vbox.pack_start(&menu_bar, false, false, 0);
@ -76,15 +75,18 @@ impl Menu {
let vbox = Rc::new(vbox); let vbox = Rc::new(vbox);
let vbox_c = Rc::clone(&vbox); let vbox_c = Rc::clone(&vbox);
self.0.lock().gtk_items.push((menu_bar, vbox)); self.0.borrow_mut().gtk_items.push((menu_bar, vbox));
vbox_c vbox_c
} }
} }
fn add_entries_to_menu<M: IsA<gtk::MenuShell>>(gtk_menu: &M, entries: &Vec<Arc<Mutex<MenuEntry>>>) { fn add_entries_to_menu<M: IsA<gtk::MenuShell>>(
gtk_menu: &M,
entries: &Vec<Rc<RefCell<MenuEntry>>>,
) {
for entry in entries { for entry in entries {
let mut entry = entry.lock(); let mut entry = entry.borrow_mut();
let gtk_item = gtk::MenuItem::with_label(&entry.label); let gtk_item = gtk::MenuItem::with_label(&entry.label);
gtk_menu.append(&gtk_item); gtk_menu.append(&gtk_item);
gtk_item.set_sensitive(entry.enabled); gtk_item.set_sensitive(entry.enabled);
@ -96,106 +98,121 @@ fn add_entries_to_menu<M: IsA<gtk::MenuShell>>(gtk_menu: &M, entries: &Vec<Arc<M
.menu_gtk_items .menu_gtk_items
.as_mut() .as_mut()
.unwrap() .unwrap()
.lock() .borrow_mut()
.push((gtk_item, gtk_menu)); .push((gtk_item, gtk_menu));
} else { } else {
let id = entry.item_id.unwrap_or_default(); let id = entry.item_id.unwrap_or_default();
gtk_item.connect_activate(move |_| { gtk_item.connect_activate(move |_| {
let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id }); let _ = crate::MENU_CHANNEL.0.send(crate::MenuEvent { id });
}); });
entry.item_gtk_items.as_mut().unwrap().lock().push(gtk_item); entry
.item_gtk_items
.as_mut()
.unwrap()
.borrow_mut()
.push(gtk_item);
} }
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Submenu(Arc<Mutex<MenuEntry>>); pub struct Submenu(Rc<RefCell<MenuEntry>>);
impl Submenu { impl Submenu {
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.0.lock().label.clone() self.0.borrow().label.clone()
} }
pub fn set_label(&mut self, label: impl AsRef<str>) { pub fn set_label(&mut self, label: impl AsRef<str>) {
let label = label.as_ref().to_string(); let label = label.as_ref().to_string();
let mut entry = self.0.lock(); let mut entry = self.0.borrow_mut();
for (item, _) in entry.menu_gtk_items.as_ref().unwrap().lock().iter() { for (item, _) in entry.menu_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_label(&label); item.set_label(&label);
} }
entry.label = label; entry.label = label;
} }
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.0.lock().enabled self.0.borrow().enabled
} }
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
let mut entry = self.0.lock(); let mut entry = self.0.borrow_mut();
entry.enabled = true; entry.enabled = true;
for (item, _) in entry.menu_gtk_items.as_ref().unwrap().lock().iter() { for (item, _) in entry.menu_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_sensitive(enabled); item.set_sensitive(enabled);
} }
} }
pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu { pub fn add_submenu(&mut self, label: impl AsRef<str>, enabled: bool) -> Submenu {
let entry = Arc::new(Mutex::new(MenuEntry { let entry = Rc::new(RefCell::new(MenuEntry {
label: label.as_ref().to_string(), label: label.as_ref().to_string(),
enabled, enabled,
entries: Some(Vec::new()), entries: Some(Vec::new()),
r#type: MenuEntryType::Submenu, r#type: MenuEntryType::Submenu,
item_id: None, item_id: None,
menu_gtk_items: Some(Arc::new(Mutex::new(Vec::new()))), menu_gtk_items: Some(Rc::new(RefCell::new(Vec::new()))),
item_gtk_items: None, item_gtk_items: None,
})); }));
self.0.lock().entries.as_mut().unwrap().push(entry.clone()); self.0
.borrow_mut()
.entries
.as_mut()
.unwrap()
.push(entry.clone());
Submenu(entry) Submenu(entry)
} }
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem { pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem {
let entry = Arc::new(Mutex::new(MenuEntry { let entry = Rc::new(RefCell::new(MenuEntry {
label: label.as_ref().to_string(), label: label.as_ref().to_string(),
enabled, enabled,
entries: None, entries: None,
r#type: MenuEntryType::Text, r#type: MenuEntryType::Text,
item_id: Some(COUNTER.next()), item_id: Some(COUNTER.next()),
menu_gtk_items: None, menu_gtk_items: None,
item_gtk_items: Some(Arc::new(Mutex::new(Vec::new()))), item_gtk_items: Some(Rc::new(RefCell::new(Vec::new()))),
})); }));
self.0.lock().entries.as_mut().unwrap().push(entry.clone()); self.0
.borrow_mut()
.entries
.as_mut()
.unwrap()
.push(entry.clone());
TextMenuItem(entry) TextMenuItem(entry)
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct TextMenuItem(Arc<Mutex<MenuEntry>>); pub struct TextMenuItem(Rc<RefCell<MenuEntry>>);
impl TextMenuItem { impl TextMenuItem {
pub fn label(&self) -> String { pub fn label(&self) -> String {
self.0.lock().label.clone() self.0.borrow().label.clone()
} }
pub fn set_label(&mut self, label: impl AsRef<str>) { pub fn set_label(&mut self, label: impl AsRef<str>) {
let label = label.as_ref().to_string(); let label = label.as_ref().to_string();
let mut entry = self.0.lock(); let mut entry = self.0.borrow_mut();
for item in entry.item_gtk_items.as_ref().unwrap().lock().iter() { for item in entry.item_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_label(&label); item.set_label(&label);
} }
entry.label = label; entry.label = label;
} }
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {
self.0.lock().enabled self.0.borrow().enabled
} }
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) {
let mut entry = self.0.lock(); let mut entry = self.0.borrow_mut();
for item in entry.item_gtk_items.as_ref().unwrap().lock().iter() { for item in entry.item_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_sensitive(enabled); item.set_sensitive(enabled);
} }
entry.enabled = enabled; entry.enabled = enabled;
} }
pub fn id(&self) -> u64 { pub fn id(&self) -> u64 {
self.0.lock().item_id.unwrap() self.0.borrow().item_id.unwrap()
} }
} }