Files
coop/crates/ui/src/menu/menu_item.rs
reya 971a82df1b
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m47s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m52s
Rust / build (macos-latest, stable) (push) Has been cancelled
Rust / build (windows-latest, stable) (push) Has been cancelled
Rust / build (macos-latest, stable) (pull_request) Has been cancelled
Rust / build (windows-latest, stable) (pull_request) Has been cancelled
add backup panel
2026-02-25 09:11:23 +07:00

126 lines
3.9 KiB
Rust

use gpui::prelude::FluentBuilder as _;
use gpui::{
AnyElement, App, ClickEvent, ElementId, InteractiveElement, IntoElement, MouseButton,
ParentElement, RenderOnce, SharedString, StatefulInteractiveElement as _, StyleRefinement,
Styled, Window,
};
use smallvec::SmallVec;
use theme::ActiveTheme;
use crate::{h_flex, Disableable, StyledExt};
#[derive(IntoElement)]
pub(crate) struct MenuItemElement {
id: ElementId,
group_name: SharedString,
style: StyleRefinement,
disabled: bool,
selected: bool,
#[allow(clippy::type_complexity)]
on_click: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
#[allow(clippy::type_complexity)]
on_hover: Option<Box<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
}
impl MenuItemElement {
/// Create a new MenuItem with the given ID and group name.
pub(crate) fn new(id: impl Into<ElementId>, group_name: impl Into<SharedString>) -> Self {
let id: ElementId = id.into();
Self {
id: id.clone(),
group_name: group_name.into(),
style: StyleRefinement::default(),
disabled: false,
selected: false,
on_click: None,
on_hover: None,
children: SmallVec::new(),
}
}
/// Set ListItem as the selected item style.
pub(crate) fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
/// Set the disabled state of the MenuItem.
pub(crate) fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
/// Set a handler for when the MenuItem is clicked.
pub(crate) fn on_click(
mut self,
handler: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
) -> Self {
self.on_click = Some(Box::new(handler));
self
}
/// Set a handler for when the mouse enters the MenuItem.
#[allow(unused)]
pub fn on_hover(mut self, handler: impl Fn(&bool, &mut Window, &mut App) + 'static) -> Self {
self.on_hover = Some(Box::new(handler));
self
}
}
impl Disableable for MenuItemElement {
fn disabled(mut self, disabled: bool) -> Self {
self.disabled = disabled;
self
}
}
impl Styled for MenuItemElement {
fn style(&mut self) -> &mut gpui::StyleRefinement {
&mut self.style
}
}
impl ParentElement for MenuItemElement {
fn extend(&mut self, elements: impl IntoIterator<Item = gpui::AnyElement>) {
self.children.extend(elements);
}
}
impl RenderOnce for MenuItemElement {
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
h_flex()
.id(self.id)
.group(&self.group_name)
.gap_x_1()
.p_1()
.text_sm()
.text_color(cx.theme().text)
.relative()
.items_center()
.justify_between()
.refine_style(&self.style)
.when_some(self.on_hover, |this, on_hover| {
this.on_hover(move |hovered, window, cx| (on_hover)(hovered, window, cx))
})
.when(!self.disabled, |this| {
this.group_hover(self.group_name, |this| {
this.bg(cx.theme().secondary_background)
.text_color(cx.theme().secondary_foreground)
})
.when(self.selected, |this| {
this.bg(cx.theme().secondary_background)
.text_color(cx.theme().secondary_foreground)
})
.when_some(self.on_click, |this, on_click| {
this.on_mouse_down(MouseButton::Left, move |_, _, cx| {
cx.stop_propagation();
})
.on_click(on_click)
})
})
.when(self.disabled, |this| this.text_color(cx.theme().text_muted))
.children(self.children)
}
}