use gpui::{Action, AppContext as _, Context, Entity, FocusHandle, Pixels, Point, Window};
use crate::actions;
use crate::icon::IconName;
use crate::overlay::ContextMenu;
pub(crate) struct EditMenu {
pub cut: bool,
pub copy: bool,
pub paste: bool,
}
impl EditMenu {
pub fn new(selection: bool, masked: bool, read_only: bool) -> Self {
EditMenu {
cut: selection && !masked && !read_only,
copy: selection && !masked,
paste: !read_only,
}
}
}
pub(crate) fn open<V: 'static>(
slot: &mut Option<Entity<ContextMenu>>,
menu: EditMenu,
focus: &FocusHandle,
position: Point<Pixels>,
window: &mut Window,
cx: &mut Context<V>,
) {
let send = |action: Box<dyn Action>| {
let focus = focus.clone();
move |window: &mut Window, cx: &mut gpui::App| {
focus.dispatch_action(action.as_ref(), window, cx)
}
};
let entity = cx.new(|cx| {
let mut m = ContextMenu::new(cx).width(180.0);
if menu.cut {
m = m.item_icon(IconName::Scissors, "Cut", send(Box::new(actions::Cut)));
}
if menu.copy {
m = m.item_icon(IconName::Copy, "Copy", send(Box::new(actions::Copy)));
}
if menu.paste {
m = m.item_icon(
IconName::ClipboardPaste,
"Paste",
send(Box::new(actions::Paste)),
);
}
if menu.cut || menu.copy || menu.paste {
m = m.divider();
}
m.item_icon(
IconName::TextSelect,
"Select All",
send(Box::new(actions::SelectAll)),
)
});
entity.update(cx, |m, cx| m.show(position, window, cx));
*slot = Some(entity);
}
pub(crate) fn is_open(slot: &Option<Entity<ContextMenu>>, cx: &gpui::App) -> bool {
slot.as_ref().is_some_and(|m| m.read(cx).is_open())
}
pub(crate) fn slot(slot: &Option<Entity<ContextMenu>>) -> Option<gpui::Div> {
use gpui::{div, ParentElement, Styled};
slot.clone().map(|m| div().absolute().child(m))
}