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]
parking_lot = "0.12"
gtk = "0.15"
[target.'cfg(target_os = "macos")'.dependencies]

View file

@ -2,8 +2,7 @@
use crate::util::Counter;
use gtk::{prelude::*, Orientation};
use parking_lot::Mutex;
use std::{rc::Rc, sync::Arc};
use std::{cell::RefCell, rc::Rc};
static COUNTER: Counter = Counter::new();
@ -22,13 +21,13 @@ struct MenuEntry {
// 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`
// and push to it every time `Menu::init_for_gtk_window` is called.
item_gtk_items: Option<Arc<Mutex<Vec<gtk::MenuItem>>>>,
menu_gtk_items: Option<Arc<Mutex<Vec<(gtk::MenuItem, gtk::Menu)>>>>,
entries: Option<Vec<Arc<Mutex<MenuEntry>>>>,
item_gtk_items: Option<Rc<RefCell<Vec<gtk::MenuItem>>>>,
menu_gtk_items: Option<Rc<RefCell<Vec<(gtk::MenuItem, gtk::Menu)>>>>,
entries: Option<Vec<Rc<RefCell<MenuEntry>>>>,
}
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`
// multiple times, and thus can't be used in multiple windows, entry
// 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>)>,
}
pub struct Menu(Arc<Mutex<InnerMenu>>);
pub struct Menu(Rc<RefCell<InnerMenu>>);
impl Menu {
pub fn new() -> Self {
Self(Arc::new(Mutex::new(InnerMenu {
Self(Rc::new(RefCell::new(InnerMenu {
entries: 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 {
let label = label.as_ref().to_string();
let entry = Arc::new(Mutex::new(MenuEntry {
let entry = Rc::new(RefCell::new(MenuEntry {
label: label.clone(),
enabled,
entries: Some(Vec::new()),
r#type: MenuEntryType::Submenu,
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,
}));
self.0.lock().entries.push(entry.clone());
self.0.borrow_mut().entries.push(entry.clone());
Submenu(entry)
}
@ -66,7 +65,7 @@ impl Menu {
W: IsA<gtk::Container>,
{
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);
vbox.pack_start(&menu_bar, false, false, 0);
@ -76,15 +75,18 @@ impl Menu {
let vbox = Rc::new(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
}
}
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 {
let mut entry = entry.lock();
let mut entry = entry.borrow_mut();
let gtk_item = gtk::MenuItem::with_label(&entry.label);
gtk_menu.append(&gtk_item);
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
.as_mut()
.unwrap()
.lock()
.borrow_mut()
.push((gtk_item, gtk_menu));
} else {
let id = entry.item_id.unwrap_or_default();
gtk_item.connect_activate(move |_| {
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)]
pub struct Submenu(Arc<Mutex<MenuEntry>>);
pub struct Submenu(Rc<RefCell<MenuEntry>>);
impl Submenu {
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>) {
let label = label.as_ref().to_string();
let mut entry = self.0.lock();
for (item, _) in entry.menu_gtk_items.as_ref().unwrap().lock().iter() {
let mut entry = self.0.borrow_mut();
for (item, _) in entry.menu_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_label(&label);
}
entry.label = label;
}
pub fn enabled(&self) -> bool {
self.0.lock().enabled
self.0.borrow().enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
let mut entry = self.0.lock();
let mut entry = self.0.borrow_mut();
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);
}
}
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(),
enabled,
entries: Some(Vec::new()),
r#type: MenuEntryType::Submenu,
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,
}));
self.0.lock().entries.as_mut().unwrap().push(entry.clone());
self.0
.borrow_mut()
.entries
.as_mut()
.unwrap()
.push(entry.clone());
Submenu(entry)
}
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(),
enabled,
entries: None,
r#type: MenuEntryType::Text,
item_id: Some(COUNTER.next()),
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)
}
}
#[derive(Clone)]
pub struct TextMenuItem(Arc<Mutex<MenuEntry>>);
pub struct TextMenuItem(Rc<RefCell<MenuEntry>>);
impl TextMenuItem {
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>) {
let label = label.as_ref().to_string();
let mut entry = self.0.lock();
for item in entry.item_gtk_items.as_ref().unwrap().lock().iter() {
let mut entry = self.0.borrow_mut();
for item in entry.item_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_label(&label);
}
entry.label = label;
}
pub fn enabled(&self) -> bool {
self.0.lock().enabled
self.0.borrow().enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
let mut entry = self.0.lock();
for item in entry.item_gtk_items.as_ref().unwrap().lock().iter() {
let mut entry = self.0.borrow_mut();
for item in entry.item_gtk_items.as_ref().unwrap().borrow().iter() {
item.set_sensitive(enabled);
}
entry.enabled = enabled;
}
pub fn id(&self) -> u64 {
self.0.lock().item_id.unwrap()
self.0.borrow().item_id.unwrap()
}
}