A disappointing introduction to menus

I wanted to add a menubar to an interface. I first found iced menu , but its documentation was so sparse that I decided to look for something else. Iced_aw has menus, and it has a nice demo with a lot of features and more documentation. So I decided to write a minimal example program to try it out:

use iced::{widget::text, Element};
use iced_aw::{menu::Item, MenuBar};

fn view(_s: &()) -> Element<()> {
    MenuBar::new(vec![Item::new(text("Menu 1"))]).into()
}

pub fn main() {
    iced::run("Minimal Menu", (), view).unwrap();
}

This compiled (with iced 0.13.1 and iced_aw 0.11.0) and runs, but after a click on the menu, panics:

thread ā€˜mainā€™ panicked at .cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_aw-0.11.0/src/widget/menu/menu_bar_overlay.rs:90:43:
called Option::unwrap() on a None value

The documentation states that MenuBar::new takes an Item, and it does not have a panics section, so this was a surprise.

Changing the view function to the following did not help much.

fn view(_s: &()) -> Element<()> {
    let root_1 = Item::with_menu(text("Menu 1"), Menu::new([].into()));
    MenuBar::new(vec![root_1]).into()
}

Clicking on the menu now leads to:

thread ā€˜mainā€™ panicked at .cargo/registry/src/index.crates.io-6f17d22bba15001f/iced_aw-0.11.0/src/widget/menu/menu_tree.rs:246:25:
index out of bounds: the len is 0 but the index is 0

The documentation of Menu::new does not state that the argument should not be an empty vector.

My third try was the following:

fn view(_s: &()) -> Element<()> {
    let root_1 = Item::with_menu(text("Menu 1"),
      Menu::new([Item::new(button("a"))].into()));
    MenuBar::new(vec![root_1]).into()
}

This program does not crash, but it doesnā€™t show the ā€œaā€ button. Why?

Looking at some examples and with some trial and error I came to:

fn view(_s: &()) -> Element<()> {
    let root_1 = Item::with_menu(
        text("Menu 1"),
        Menu::new([Item::new(button("a").on_press(()))].into()).max_width(50.0),
    );
    MenuBar::new(vec![root_1]).into()
}

Apparently I need to call max_width. Again something I would have liked to see in the documentation.

All in all, I canā€™t say Iā€™m happy with my first acquaintance with this library. I see that the releases of both iced and iced_aw start with 0, so perhaps I should just wait for things to mature. On the other hand, iced seems to be one of the most mature Rust GUIs and an application with a menu bar is quite standard. So, isnā€™t there really not something better?

1 Like

I hear you, menus are frustrating right now. As painful as they are, I wouldnā€™t dismiss the library entirely because of this particular issue. Iced is experimental, as you alluded to in your comment about the version number. And context menus are on the roadmap for the next version: Roadmap - iced

Many people dislike the API in iced_aw (which is a third-party crate, by the way). Most of them still seem to use it after fighting with it for a while.

Some people have written their own versions of menusā€¦ One example I saw mentioned on the Discord is here: punge/src/gui/widgets at master Ā· nednoodlehead/punge Ā· GitHub

I decided to punt this issue to later and focus on other parts of the app but I understand that is not viable for some apps. Just wanted to say thereā€™s way more to iced than menus and dismissing the library for this understandably frustrating issue would be a mistake IMHO