Add an actual context menu into terminal-2
(click the text, not the pane!) Co-Authored-By: Piotr <piotr@zed.dev>
This commit is contained in:
parent
f638d4ce1d
commit
ab0a3f19ab
12 changed files with 112 additions and 646 deletions
|
@ -3,17 +3,29 @@ use crate::{v_stack, Label, List, ListEntry, ListItem, ListSeparator, ListSubHea
|
|||
|
||||
pub enum ContextMenuItem {
|
||||
Header(SharedString),
|
||||
Entry(Label),
|
||||
Entry(Label, Box<dyn gpui::Action>),
|
||||
Separator,
|
||||
}
|
||||
|
||||
impl Clone for ContextMenuItem {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
ContextMenuItem::Header(name) => ContextMenuItem::Header(name.clone()),
|
||||
ContextMenuItem::Entry(label, action) => {
|
||||
ContextMenuItem::Entry(label.clone(), action.boxed_clone())
|
||||
}
|
||||
ContextMenuItem::Separator => ContextMenuItem::Separator,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ContextMenuItem {
|
||||
fn to_list_item<V: 'static>(self) -> ListItem {
|
||||
match self {
|
||||
ContextMenuItem::Header(label) => ListSubHeader::new(label).into(),
|
||||
ContextMenuItem::Entry(label) => {
|
||||
ListEntry::new(label).variant(ListItemVariant::Inset).into()
|
||||
}
|
||||
ContextMenuItem::Entry(label, action) => ListEntry::new(label)
|
||||
.variant(ListItemVariant::Inset)
|
||||
.on_click(action)
|
||||
.into(),
|
||||
ContextMenuItem::Separator => ListSeparator::new().into(),
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +38,12 @@ impl ContextMenuItem {
|
|||
Self::Separator
|
||||
}
|
||||
|
||||
pub fn entry(label: Label) -> Self {
|
||||
Self::Entry(label)
|
||||
pub fn entry(label: Label, action: impl Action) -> Self {
|
||||
Self::Entry(label, Box::new(action))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Clone)]
|
||||
pub struct ContextMenu {
|
||||
items: Vec<ContextMenuItem>,
|
||||
}
|
||||
|
@ -42,7 +54,12 @@ impl ContextMenu {
|
|||
items: items.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
// todo!()
|
||||
// cx.add_action(ContextMenu::select_first);
|
||||
// cx.add_action(ContextMenu::select_last);
|
||||
// cx.add_action(ContextMenu::select_next);
|
||||
// cx.add_action(ContextMenu::select_prev);
|
||||
// cx.add_action(ContextMenu::confirm);
|
||||
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
|
||||
v_stack()
|
||||
.flex()
|
||||
|
@ -55,9 +72,11 @@ impl ContextMenu {
|
|||
.map(ContextMenuItem::to_list_item::<V>)
|
||||
.collect(),
|
||||
))
|
||||
.on_mouse_down_out(|_, _, cx| cx.dispatch_action(Box::new(menu::Cancel)))
|
||||
}
|
||||
}
|
||||
|
||||
use gpui::Action;
|
||||
#[cfg(feature = "stories")]
|
||||
pub use stories::*;
|
||||
|
||||
|
@ -65,7 +84,7 @@ pub use stories::*;
|
|||
mod stories {
|
||||
use super::*;
|
||||
use crate::story::Story;
|
||||
use gpui::{Div, Render};
|
||||
use gpui::{action, Div, Render};
|
||||
|
||||
pub struct ContextMenuStory;
|
||||
|
||||
|
@ -73,14 +92,22 @@ mod stories {
|
|||
type Element = Div<Self>;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
#[action]
|
||||
struct PrintCurrentDate {}
|
||||
|
||||
Story::container(cx)
|
||||
.child(Story::title_for::<_, ContextMenu>(cx))
|
||||
.child(Story::label(cx, "Default"))
|
||||
.child(ContextMenu::new([
|
||||
ContextMenuItem::header("Section header"),
|
||||
ContextMenuItem::Separator,
|
||||
ContextMenuItem::entry(Label::new("Some entry")),
|
||||
ContextMenuItem::entry(Label::new("Print current time"), PrintCurrentDate {}),
|
||||
]))
|
||||
.on_action(|_, _: &PrintCurrentDate, _| {
|
||||
if let Ok(unix_time) = std::time::UNIX_EPOCH.elapsed() {
|
||||
println!("Current Unix time is {:?}", unix_time.as_secs());
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue