grx/gtk_components/
menu.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3//! The basic button component
4
5use self::menu_item::MenuItem;
6use crate::{new_gc, props};
7use glib::prelude::Cast;
8use grx_macros::gtk_component;
9use gtk::glib;
10use gtk::prelude::WidgetExt;
11use std::rc::Rc;
12
13use super::gtk_props::apply;
14
15#[props]
16#[derive(Default, Debug)]
17pub struct Props {
18    pub items: Vec<MenuItem>,
19}
20
21pub fn menu(mut props: Props) -> Rc<Menu> {
22    let model = gtk::gio::Menu::new();
23    for item in &props.items {
24        model.append(Some(&item.label), item.action.as_deref());
25    }
26    let menu = gtk::PopoverMenu::from_model(Some(&model));
27    let widget = menu.upcast();
28    let comp = new_gc!(Menu { widget, props });
29    apply(comp.clone());
30    comp
31}
32
33#[gtk_component(gtk::Widget)]
34#[derive(Debug)]
35pub struct Menu {}
36
37impl Menu {
38    pub fn show(self: &Rc<Self>) {
39        self.widget.set_visible(true);
40    }
41}
42
43pub mod menu_item {
44    use gstore::Actionable;
45
46    pub fn menu_item(label: String, action: Option<impl Actionable>) -> MenuItem {
47        MenuItem {
48            label,
49            action: action.map(|s| format!("app.{}", s.name())),
50        }
51    }
52
53    #[derive(Debug, Clone)]
54    pub struct MenuItem {
55        pub label: String,
56        pub action: Option<String>,
57    }
58}