Components / Menus & actions
Menubar
Markdown crates/ui/src/menubar.rs docs.rs
use ui::menu::Item;
use ui::menubar::{self, Menu, Menubar, MenubarEvent};
menubar::init(cx); // once, at startup
let bar = cx.new(|cx| Menubar::new(vec![
Menu::new("File", vec![
Item::action("New Window").with_keystroke("⌘N"),
Item::submenu("Open Recent", vec![
Item::action("bezel.md"),
Item::Separator,
Item::action("Clear Menu"),
]),
Item::Separator,
Item::action("Close").with_keystroke("⌘W").disabled(),
]),
], cx));
cx.subscribe(&bar, |_, bar, event, cx| {
let MenubarEvent::Selected { menu, path } = event;
let item = bar.read(cx).menus()[*menu].at(path); // /* dispatch */
})
.detach();Not the native bar — on macOS that is cx.set_menus and four lines in main. This is the bar an app with a custom titlebar draws for itself.
API
// ui::menubar
pub fn init(cx: &mut App);
impl Menubar {
/// Sliding onto a sibling title switches to it with no click; `left` and
/// `right` cross between menus.
pub fn new(menus: Vec<Menu>, cx: &mut Context<Self>) -> Self;
// ...
}
/// A path — one row index per level, outermost first. `Menu::at` turns it back
/// into the item.
pub enum MenubarEvent { Selected { menu: usize, path: Vec<usize> } }// ui::menu — shaped like gpui's own `Menu` and `MenuItem`, so an app drawing
// both bars writes them the same way.
impl Item {
pub fn action(label: impl Into<SharedString>) -> Self;
pub fn submenu(label: impl Into<SharedString>, items: Vec<Item>) -> Self;
/// The accelerator to **print**. The binding is the app's; bezel never
/// dispatches it.
pub fn with_keystroke(self, keystroke: impl Into<SharedString>) -> Self;
pub fn checked(self, checked: bool) -> Self;
pub fn disabled(self) -> Self;
// ...
}
/// Steps over separators and disabled rows, wraps at both ends, and answers
/// `None` when nothing can be landed on.
pub fn next_selectable(items: &[Item], from: Option<usize>, delta: isize) -> Option<usize>;