zed/crates/gpui/examples/set_menus.rs
Jason Lee 61c2a4334c
gpui: Add disabled state to app menu items (#44191)
Continue #39876 to add `disabled` state to `MenuItem`.

Make this change for #44047 ready to have disabled state.

1. Add `disabled` state to `MenuItem`.
2. Add some builder methods to `Menu` and `MenuItem`.
3. Improve `set_menus` method to receive a `impl IntoIterator<Item =
Menu>`.

Release Notes:

- N/A

--

<img width="294" height="204" alt="image"
src="https://github.com/user-attachments/assets/688e0db8-6c4e-4f9b-a832-8228db0e95d8"
/>

```bash
cargo run -p gpui --example set_menus
```
2026-03-20 11:00:00 +00:00

128 lines
3.3 KiB
Rust

#![cfg_attr(target_family = "wasm", no_main)]
use gpui::{
App, Context, Global, Menu, MenuItem, SharedString, SystemMenuType, Window, WindowOptions,
actions, div, prelude::*,
};
use gpui_platform::application;
struct SetMenus;
impl Render for SetMenus {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.flex()
.bg(gpui::white())
.size_full()
.justify_center()
.items_center()
.text_xl()
.text_color(gpui::black())
.child("Set Menus Example")
}
}
fn run_example() {
application().run(|cx: &mut App| {
cx.set_global(AppState::new());
// Bring the menu bar to the foreground (so you can see the menu bar)
cx.activate(true);
// Register the `quit` function so it can be referenced
// by the `MenuItem::action` in the menu bar
cx.on_action(quit);
cx.on_action(toggle_check);
// Add menu items
set_app_menus(cx);
cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| SetMenus {}))
.unwrap();
});
}
#[cfg(not(target_family = "wasm"))]
fn main() {
run_example();
}
#[cfg(target_family = "wasm")]
#[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn start() {
gpui_platform::web_init();
run_example();
}
#[derive(PartialEq)]
enum ViewMode {
List,
Grid,
}
impl ViewMode {
fn toggle(&mut self) {
*self = match self {
ViewMode::List => ViewMode::Grid,
ViewMode::Grid => ViewMode::List,
}
}
}
impl Into<SharedString> for ViewMode {
fn into(self) -> SharedString {
match self {
ViewMode::List => "List",
ViewMode::Grid => "Grid",
}
.into()
}
}
struct AppState {
view_mode: ViewMode,
}
impl AppState {
fn new() -> Self {
Self {
view_mode: ViewMode::List,
}
}
}
impl Global for AppState {}
fn set_app_menus(cx: &mut App) {
let app_state = cx.global::<AppState>();
cx.set_menus([Menu::new("set_menus").items([
MenuItem::os_submenu("Services", SystemMenuType::Services),
MenuItem::separator(),
MenuItem::action("Disabled Item", gpui::NoAction).disabled(true),
MenuItem::submenu(Menu::new("Disabled Submenu").disabled(true)),
MenuItem::separator(),
MenuItem::action("List Mode", ToggleCheck).checked(app_state.view_mode == ViewMode::List),
MenuItem::submenu(
Menu::new("Mode").items([
MenuItem::action(ViewMode::List, ToggleCheck)
.checked(app_state.view_mode == ViewMode::List),
MenuItem::action(ViewMode::Grid, ToggleCheck)
.checked(app_state.view_mode == ViewMode::Grid),
]),
),
MenuItem::separator(),
MenuItem::action("Quit", Quit),
])]);
}
// Associate actions using the `actions!` macro (or `Action` derive macro)
actions!(set_menus, [Quit, ToggleCheck]);
// Define the quit function that is registered with the App
fn quit(_: &Quit, cx: &mut App) {
println!("Gracefully quitting the application...");
cx.quit();
}
fn toggle_check(_: &ToggleCheck, cx: &mut App) {
let app_state = cx.global_mut::<AppState>();
app_state.view_mode.toggle();
set_app_menus(cx);
}