add menu item handler on linux

This commit is contained in:
amrbashir 2022-05-05 17:04:48 +02:00
parent a46c53dbe9
commit cff1103cf4
No known key found for this signature in database
GPG key ID: BBD7A47A2003FF33
4 changed files with 56 additions and 47 deletions

View file

@ -17,12 +17,15 @@ fn main() {
let mut file_menu = menu_bar.add_submenu("File", true); let mut file_menu = menu_bar.add_submenu("File", true);
let mut edit_menu = menu_bar.add_submenu("Edit", true); let mut edit_menu = menu_bar.add_submenu("Edit", true);
let _open_item = file_menu.add_text_item("Open", true); let _open_item = file_menu.add_text_item("Open", true, |_| {});
let mut save_item = file_menu.add_text_item("Save", true); let _save_item = file_menu.add_text_item("Save", true, |i| {
let _quit_item = file_menu.add_text_item("Quit", true); i.set_enabled(false);
i.set_label("Save disabled");
});
let _quit_item = file_menu.add_text_item("Quit", true, |_| {});
let _copy_item = edit_menu.add_text_item("Copy", true); let _copy_item = edit_menu.add_text_item("Copy", true, |_| {});
let _cut_item = edit_menu.add_text_item("Cut", true); let _cut_item = edit_menu.add_text_item("Cut", true, |_| {});
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
menu_bar.init_for_hwnd(window.hwnd() as _); menu_bar.init_for_hwnd(window.hwnd() as _);
@ -38,10 +41,7 @@ fn main() {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => *control_flow = ControlFlow::Exit,
save_item.set_enabled(false);
save_item.set_label("Save disabled");
}
Event::MainEventsCleared => { Event::MainEventsCleared => {
window.request_redraw(); window.request_redraw();
} }

View file

@ -14,12 +14,15 @@ fn main() {
let mut file_menu = menu_bar.add_submenu("File", true); let mut file_menu = menu_bar.add_submenu("File", true);
let mut edit_menu = menu_bar.add_submenu("Edit", true); let mut edit_menu = menu_bar.add_submenu("Edit", true);
let _open_item = file_menu.add_text_item("Open", true); let _open_item = file_menu.add_text_item("Open", true, |_| {});
let mut save_item = file_menu.add_text_item("Save", true); let _save_item = file_menu.add_text_item("Save", true, |i| {
let _quit_item = file_menu.add_text_item("Quit", true); i.set_enabled(false);
i.set_label("Save disabled");
});
let _quit_item = file_menu.add_text_item("Quit", true, |_| {});
let _copy_item = edit_menu.add_text_item("Copy", true); let _copy_item = edit_menu.add_text_item("Copy", true, |_| {});
let _cut_item = edit_menu.add_text_item("Cut", true); let _cut_item = edit_menu.add_text_item("Cut", true, |_| {});
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
menu_bar.init_for_hwnd(window.hwnd() as _); menu_bar.init_for_hwnd(window.hwnd() as _);
@ -31,9 +34,7 @@ fn main() {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => *control_flow = ControlFlow::Exit,
save_item.set_enabled(false);
}
Event::MainEventsCleared => { Event::MainEventsCleared => {
window.request_redraw(); window.request_redraw();
} }

View file

@ -12,10 +12,6 @@ impl Menu {
Submenu(self.0.add_submenu(label, enabled)) Submenu(self.0.add_submenu(label, enabled))
} }
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem {
TextMenuItem(self.0.add_text_item(label, enabled))
}
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn init_for_gtk_window<W>(&self, w: &W) pub fn init_for_gtk_window<W>(&self, w: &W)
where where
@ -40,8 +36,13 @@ impl Submenu {
Submenu(self.0.add_submenu(label, enabled)) Submenu(self.0.add_submenu(label, enabled))
} }
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem { pub fn add_text_item<F: FnMut(&mut TextMenuItem) + 'static>(
TextMenuItem(self.0.add_text_item(label, enabled)) &mut self,
label: impl AsRef<str>,
enabled: bool,
f: F,
) -> TextMenuItem {
TextMenuItem(self.0.add_text_item(label, enabled, f))
} }
} }

View file

@ -1,5 +1,5 @@
use parking_lot::Mutex; use parking_lot::Mutex;
use std::sync::Arc; use std::{cell::RefCell, rc::Rc, sync::Arc};
use gtk::{prelude::*, Orientation}; use gtk::{prelude::*, Orientation};
@ -17,6 +17,8 @@ struct MenuEntry {
enabled: bool, enabled: bool,
entries: Option<Vec<Arc<Mutex<MenuEntry>>>>, entries: Option<Vec<Arc<Mutex<MenuEntry>>>>,
etype: MenuEntryType, etype: MenuEntryType,
item_handler: Option<Rc<RefCell<dyn FnMut(&mut crate::TextMenuItem) + 'static>>>,
item_id: Option<u64>,
menu_gtk_items: Option<Arc<Mutex<Vec<(gtk::MenuItem, gtk::Menu)>>>>, menu_gtk_items: Option<Arc<Mutex<Vec<(gtk::MenuItem, gtk::Menu)>>>>,
item_gtk_items: Option<Arc<Mutex<Vec<gtk::MenuItem>>>>, item_gtk_items: Option<Arc<Mutex<Vec<gtk::MenuItem>>>>,
} }
@ -44,6 +46,8 @@ impl Menu {
enabled, enabled,
entries: Some(Vec::new()), entries: Some(Vec::new()),
etype: MenuEntryType::Submenu, etype: MenuEntryType::Submenu,
item_handler: None,
item_id: None,
menu_gtk_items: Some(gtk_items.clone()), menu_gtk_items: Some(gtk_items.clone()),
item_gtk_items: None, item_gtk_items: None,
})); }));
@ -56,27 +60,6 @@ impl Menu {
} }
} }
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem {
let label = label.as_ref().to_string();
let gtk_items = Arc::new(Mutex::new(Vec::new()));
let entry = Arc::new(Mutex::new(MenuEntry {
label: label.clone(),
enabled,
entries: None,
etype: MenuEntryType::Text,
menu_gtk_items: None,
item_gtk_items: Some(gtk_items.clone()),
}));
self.0.lock().entries.push(entry.clone());
TextMenuItem {
label,
enabled,
entry,
gtk_items,
id: COUNTER.next(),
}
}
pub fn init_for_gtk_window<W>(&self, w: &W) pub fn init_for_gtk_window<W>(&self, w: &W)
where where
W: IsA<gtk::Container>, W: IsA<gtk::Container>,
@ -95,6 +78,7 @@ impl Menu {
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<Arc<Mutex<MenuEntry>>>) {
for entry in entries { for entry in entries {
let entry_clone = entry.clone();
let mut entry = entry.lock(); let mut entry = entry.lock();
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);
@ -110,6 +94,19 @@ fn add_entries_to_menu<M: IsA<gtk::MenuShell>>(gtk_menu: &M, entries: &Vec<Arc<M
.lock() .lock()
.push((gtk_item, gtk_menu)); .push((gtk_item, gtk_menu));
} else { } else {
let handler = Rc::clone(&entry.item_handler.as_mut().unwrap());
let item = TextMenuItem {
label: entry.label.clone(),
enabled: entry.enabled,
id: entry.item_id.unwrap(),
entry: entry_clone,
gtk_items: entry.item_gtk_items.as_ref().unwrap().clone(),
};
gtk_item.connect_activate(move |_| {
let mut handler = handler.borrow_mut();
let mut item = crate::TextMenuItem(item.clone());
handler(&mut item);
});
entry.item_gtk_items.as_mut().unwrap().lock().push(gtk_item); entry.item_gtk_items.as_mut().unwrap().lock().push(gtk_item);
} }
} }
@ -151,6 +148,8 @@ impl Submenu {
enabled, enabled,
entries: Some(Vec::new()), entries: Some(Vec::new()),
etype: MenuEntryType::Submenu, etype: MenuEntryType::Submenu,
item_handler: None,
item_id: None,
menu_gtk_items: Some(gtk_items.clone()), menu_gtk_items: Some(gtk_items.clone()),
item_gtk_items: None, item_gtk_items: None,
})); }));
@ -168,7 +167,13 @@ impl Submenu {
} }
} }
pub fn add_text_item(&mut self, label: impl AsRef<str>, enabled: bool) -> TextMenuItem { pub fn add_text_item<F: FnMut(&mut crate::TextMenuItem) + 'static>(
&mut self,
label: impl AsRef<str>,
enabled: bool,
f: F,
) -> TextMenuItem {
let id = COUNTER.next();
let label = label.as_ref().to_string(); let label = label.as_ref().to_string();
let gtk_items = Arc::new(Mutex::new(Vec::new())); let gtk_items = Arc::new(Mutex::new(Vec::new()));
let entry = Arc::new(Mutex::new(MenuEntry { let entry = Arc::new(Mutex::new(MenuEntry {
@ -176,6 +181,8 @@ impl Submenu {
enabled, enabled,
entries: None, entries: None,
etype: MenuEntryType::Text, etype: MenuEntryType::Text,
item_handler: Some(Rc::new(RefCell::new(f))),
item_id: Some(id),
menu_gtk_items: None, menu_gtk_items: None,
item_gtk_items: Some(gtk_items.clone()), item_gtk_items: Some(gtk_items.clone()),
})); }));
@ -190,7 +197,7 @@ impl Submenu {
enabled, enabled,
entry, entry,
gtk_items, gtk_items,
id: COUNTER.next(), id,
} }
} }
} }