use crate::view::{root::Cydonia, sidebar::Row};
use bezel::{
gpui::{self, AnyElement, Context, Div, SharedString, Stateful, Window, prelude::*, px},
theme::Theme,
ui::{
menu::{self, Item},
widgets::Buttons,
},
};
type Act = Box<dyn Fn(&mut Cydonia, &mut Window, &mut Context<Cydonia>)>;
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum Menu {
Add(usize),
Project(usize),
Entry(Row),
Filter,
Column(usize),
}
pub(crate) fn row(
item: Item,
act: impl Fn(&mut Cydonia, &mut Window, &mut Context<Cydonia>) + 'static,
) -> (Item, Act) {
(item, Box::new(act))
}
impl Cydonia {
pub(crate) fn toggle_menu(&mut self, menu: Menu, cx: &mut Context<Self>) {
let closed_by_this_press = std::mem::take(&mut self.menu_pressed);
self.menu = (!closed_by_this_press && self.menu != Some(menu)).then_some(menu);
cx.notify();
}
pub(crate) fn menu_press(
&self,
el: Stateful<Div>,
menu: Menu,
cx: &Context<Self>,
) -> Stateful<Div> {
el.capture_any_mouse_down(cx.listener(move |this, _, _, _| {
this.menu_pressed = this.menu == Some(menu);
}))
}
pub(crate) fn menu_button(
&self,
id: impl Into<gpui::ElementId>,
group: &'static str,
mark: impl IntoElement,
menu: Menu,
cx: &Context<Self>,
) -> Stateful<Div> {
let button = Theme::of(cx)
.ghost(id)
.flex_none()
.relative()
.when(self.menu != Some(menu), |el| {
el.invisible().group_hover(group, |el| el.visible())
})
.p(px(3.))
.child(mark)
.on_click(cx.listener(move |this, _, _, cx| {
cx.stop_propagation();
this.toggle_menu(menu, cx);
}));
self.menu_press(button, menu, cx)
}
pub(crate) fn menu_card(
&self,
id: impl Into<SharedString>,
rows: Vec<(Item, Act)>,
cx: &mut Context<Self>,
) -> AnyElement {
let theme = Theme::of(cx).clone();
let (items, acts): (Vec<Item>, Vec<Act>) = rows.into_iter().unzip();
menu::card(&theme, id, &items, None, cx, move |this, ix, window, cx| {
this.menu = None;
acts[ix](this, window, cx);
cx.notify();
})
.on_mouse_down_out(cx.listener(|this, _, _, cx| {
this.menu = None;
cx.notify();
}))
.into_any_element()
}
}