gpui: Add to support check state to MenuItem (#39876)

Release Notes:

- N/A

---


https://github.com/user-attachments/assets/d46b77ae-88ba-43da-93ad-3656a7fecaf9

The system menu is only support for macOS, so here just modify the macOS
platform special code.

The Windows, Linux used `ApplicationMenu`, I have already added
`checked` option to Zed's ContextMenu.

Then later when this PR merged, we can improve "View" menu to show check
state to panels (Project Panel, Outline Panel, ...).
This commit is contained in:
Jason Lee
2025-11-07 09:42:55 +00:00
committed by GitHub
parent 760747f127
commit 29cc3d0e18
6 changed files with 137 additions and 20 deletions
+34 -2
View File
@@ -64,12 +64,15 @@ pub enum MenuItem {
/// The name of this menu item
name: SharedString,
/// the action to perform when this menu item is selected
/// The action to perform when this menu item is selected
action: Box<dyn Action>,
/// The OS Action that corresponds to this action, if any
/// See [`OsAction`] for more information
os_action: Option<OsAction>,
/// Whether this action is checked
checked: bool,
},
}
@@ -98,6 +101,7 @@ impl MenuItem {
name: name.into(),
action: Box::new(action),
os_action: None,
checked: false,
}
}
@@ -111,6 +115,7 @@ impl MenuItem {
name: name.into(),
action: Box::new(action),
os_action: Some(os_action),
checked: false,
}
}
@@ -123,14 +128,36 @@ impl MenuItem {
name,
action,
os_action,
checked,
} => OwnedMenuItem::Action {
name: name.into(),
action,
os_action,
checked,
},
MenuItem::SystemMenu(os_menu) => OwnedMenuItem::SystemMenu(os_menu.owned()),
}
}
/// Set whether this menu item is checked
///
/// Only for [`MenuItem::Action`], otherwise, will be ignored
pub fn checked(mut self, checked: bool) -> Self {
match self {
MenuItem::Action {
action,
os_action,
name,
..
} => MenuItem::Action {
name,
action,
os_action,
checked,
},
_ => self,
}
}
}
/// OS menus are menus that are recognized by the operating system
@@ -171,12 +198,15 @@ pub enum OwnedMenuItem {
/// The name of this menu item
name: String,
/// the action to perform when this menu item is selected
/// The action to perform when this menu item is selected
action: Box<dyn Action>,
/// The OS Action that corresponds to this action, if any
/// See [`OsAction`] for more information
os_action: Option<OsAction>,
/// Whether this action is checked
checked: bool,
},
}
@@ -189,10 +219,12 @@ impl Clone for OwnedMenuItem {
name,
action,
os_action,
checked,
} => OwnedMenuItem::Action {
name: name.clone(),
action: action.boxed_clone(),
os_action: *os_action,
checked: *checked,
},
OwnedMenuItem::SystemMenu(os_menu) => OwnedMenuItem::SystemMenu(os_menu.clone()),
}
+6 -1
View File
@@ -19,7 +19,7 @@ use cocoa::{
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
NSEventModifierFlags, NSMenu, NSMenuItem, NSModalResponse, NSOpenPanel, NSPasteboard,
NSPasteboardTypePNG, NSPasteboardTypeRTF, NSPasteboardTypeRTFD, NSPasteboardTypeString,
NSPasteboardTypeTIFF, NSSavePanel, NSWindow,
NSPasteboardTypeTIFF, NSSavePanel, NSVisualEffectState, NSVisualEffectView, NSWindow,
},
base::{BOOL, NO, YES, id, nil, selector},
foundation::{
@@ -315,6 +315,7 @@ impl MacPlatform {
name,
action,
os_action,
checked,
} => {
// Note that this is intentionally using earlier bindings, whereas typically
// later ones take display precedence. See the discussion on
@@ -409,6 +410,10 @@ impl MacPlatform {
.autorelease();
}
if *checked {
item.setState_(NSVisualEffectState::Active);
}
let tag = actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag];
actions.push(action.boxed_clone());