relm4_macros

Macro menu

source
menu!() { /* proc-macro */ }
Expand description

A macro to create menus.

Use

  • "Label text" => ActionType, to create new entries.
  • "Label text" => ActionType(value), to create new entries with action value.
  • custom => "widget_id", add a placeholder for custom widgets you can add later with set_attribute_name.
  • section! { ... } to create new sections.

§Example

// Define some actions
relm4::new_action_group!(WindowActionGroup, "win");
relm4::new_stateless_action!(TestAction, WindowActionGroup, "test");
relm4::new_stateful_action!(TestU8Action, WindowActionGroup, "test2", u8, u8);

// Create a `MenuModel` called `menu_model`
relm4_macros::menu! {
    main_menu: {
        custom: "my_widget",
        // Translate with gettext-rs, for example.
        &gettext("Test") => TestAction,
        "Test2" => TestAction,
        "Test toggle" => TestU8Action(1_u8),
        section! {
            "Section test" => TestAction,
            "Test toggle" => TestU8Action(1_u8),
        },
        section! {
            "Test" => TestAction,
            "Test2" => TestAction,
            "Test Value" => TestU8Action(1_u8),
        }
    }
};

§Macro expansion

The code generation for the example above looks like this (plus comments):

struct WindowActionGroup;
impl relm4::actions::ActionGroupName for WindowActionGroup {
    const NAME: &'static str = "win";
}

struct TestAction;
impl relm4::actions::ActionName for TestAction {
    type Group = WindowActionGroup;
    type State = ();
    type Target = ();

    const NAME: &'static str = "test";
}

struct TestU8Action;
impl relm4::actions::ActionName for TestU8Action {
    type Group = WindowActionGroup;
    type State = u8;
    type Target = u8;

    const NAME: &'static str = "test2";
}

// Main menu
let main_menu = relm4::gtk::gio::Menu::new();

// Placeholder for custom widget
let new_entry = relm4::gtk::gio::MenuItem::new(None, None);
let variant = relm4::gtk::glib::variant::ToVariant::to_variant("my_widget");
new_entry.set_attribute_value("custom", Some(&variant));
main_menu.append_item(&new_entry);

let new_entry = relm4::actions::RelmAction::<TestAction>::to_menu_item(&gettext("Test"));
main_menu.append_item(&new_entry);
let new_entry = relm4::actions::RelmAction::<TestAction>::to_menu_item("Test2");
main_menu.append_item(&new_entry);
let new_entry = relm4::actions::RelmAction::<TestU8Action>::to_menu_item_with_target_value(
    "Test toggle",
    &1_u8,
);
main_menu.append_item(&new_entry);

// Section 0
let _section_0 = relm4::gtk::gio::Menu::new();
main_menu.append_section(None, &_section_0);
let new_entry = relm4::actions::RelmAction::<TestAction>::to_menu_item("Section test");
_section_0.append_item(&new_entry);
let new_entry = relm4::actions::RelmAction::<TestU8Action>::to_menu_item_with_target_value(
    "Test toggle",
    &1_u8,
);
_section_0.append_item(&new_entry);

// Section 1
let _section_1 = relm4::gtk::gio::Menu::new();
main_menu.append_section(None, &_section_1);
let new_entry = relm4::actions::RelmAction::<TestAction>::to_menu_item("Test");
_section_1.append_item(&new_entry);
let new_entry = relm4::actions::RelmAction::<TestAction>::to_menu_item("Test2");
_section_1.append_item(&new_entry);
let new_entry = relm4::actions::RelmAction::<TestU8Action>::to_menu_item_with_target_value(
    "Test Value",
    &1_u8,
);
_section_1.append_item(&new_entry);