grx 0.2.0

Abstraction layer for UI development
// SPDX-License-Identifier: GPL-3.0-or-later

//! The basic button component

use self::menu_item::MenuItem;
use crate::{new_gc, props};
use glib::Cast;
use grx_macros::gtk_component;
use gtk::glib;
use gtk::traits::WidgetExt;
use std::rc::Rc;

use super::gtk_props::apply;

#[props]
#[derive(Default, Debug)]
pub struct Props {
    pub items: Vec<MenuItem>,
}

pub fn menu(mut props: Props) -> Rc<Menu> {
    let model = gtk::gio::Menu::new();
    for item in &props.items {
        model.append(Some(&item.label), item.action.as_deref());
    }
    let menu = gtk::PopoverMenu::from_model(Some(&model));
    let widget = menu.upcast();
    let comp = new_gc!(Menu { widget, props });
    apply(comp.clone());
    comp
}

#[gtk_component(gtk::Widget)]
#[derive(Debug)]
pub struct Menu {}

impl Menu {
    pub fn show(self: &Rc<Self>) {
        self.widget.set_visible(true);
    }
}

pub mod menu_item {
    use gstore::Actionable;

    pub fn menu_item(label: String, action: Option<impl Actionable>) -> MenuItem {
        MenuItem {
            label,
            action: action.map(|s| format!("app.{}", s.name())),
        }
    }

    #[derive(Debug, Clone)]
    pub struct MenuItem {
        pub label: String,
        pub action: Option<String>,
    }
}