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());
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ pub enum LineHeightStyle {
|
|||
UILabel,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Clone, Component)]
|
||||
pub struct Label {
|
||||
label: SharedString,
|
||||
size: LabelSize,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use gpui::div;
|
||||
use gpui::{div, Action};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::settings::user_settings;
|
||||
use crate::{
|
||||
disclosure_control, h_stack, v_stack, Avatar, GraphicSlot, Icon, IconElement, IconSize, Label,
|
||||
TextColor, Toggle,
|
||||
disclosure_control, h_stack, v_stack, Avatar, Icon, IconElement, IconSize, Label, Toggle,
|
||||
};
|
||||
use crate::{prelude::*, GraphicSlot};
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq)]
|
||||
pub enum ListItemVariant {
|
||||
|
@ -232,6 +231,7 @@ pub struct ListEntry {
|
|||
size: ListEntrySize,
|
||||
toggle: Toggle,
|
||||
variant: ListItemVariant,
|
||||
on_click: Option<Box<dyn Action>>,
|
||||
}
|
||||
|
||||
impl ListEntry {
|
||||
|
@ -245,9 +245,15 @@ impl ListEntry {
|
|||
size: ListEntrySize::default(),
|
||||
toggle: Toggle::NotToggleable,
|
||||
variant: ListItemVariant::default(),
|
||||
on_click: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_click(mut self, action: impl Into<Box<dyn Action>>) -> Self {
|
||||
self.on_click = Some(action.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn variant(mut self, variant: ListItemVariant) -> Self {
|
||||
self.variant = variant;
|
||||
self
|
||||
|
@ -303,9 +309,21 @@ impl ListEntry {
|
|||
ListEntrySize::Small => div().h_6(),
|
||||
ListEntrySize::Medium => div().h_7(),
|
||||
};
|
||||
|
||||
div()
|
||||
.relative()
|
||||
.hover(|mut style| {
|
||||
style.background = Some(cx.theme().colors().editor_background.into());
|
||||
style
|
||||
})
|
||||
.on_mouse_down(gpui::MouseButton::Left, {
|
||||
let action = self.on_click.map(|action| action.boxed_clone());
|
||||
|
||||
move |entry: &mut V, event, cx| {
|
||||
if let Some(action) = action.as_ref() {
|
||||
cx.dispatch_action(action.boxed_clone());
|
||||
}
|
||||
}
|
||||
})
|
||||
.group("")
|
||||
.bg(cx.theme().colors().surface_background)
|
||||
// TODO: Add focus state
|
||||
|
@ -401,7 +419,7 @@ impl List {
|
|||
v_stack()
|
||||
.w_full()
|
||||
.py_1()
|
||||
.children(self.header)
|
||||
.children(self.header.map(|header| header))
|
||||
.child(list_content)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue