Use ListItem
when rendering picker matches
This commit is contained in:
parent
63bd4ac999
commit
1ee109cec7
3 changed files with 33 additions and 64 deletions
|
@ -1,17 +1,15 @@
|
||||||
use collections::{CommandPaletteFilter, HashMap};
|
use collections::{CommandPaletteFilter, HashMap};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, prelude::*, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
|
actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||||
FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext,
|
Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||||
WeakView,
|
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Reverse},
|
cmp::{self, Reverse},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, ListItem};
|
||||||
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, StyledExt};
|
|
||||||
use util::{
|
use util::{
|
||||||
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
||||||
ResultExt,
|
ResultExt,
|
||||||
|
@ -141,7 +139,7 @@ impl CommandPaletteDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for CommandPaletteDelegate {
|
impl PickerDelegate for CommandPaletteDelegate {
|
||||||
type ListItem = Div;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Execute a command...".into()
|
"Execute a command...".into()
|
||||||
|
@ -295,7 +293,6 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Option<Self::ListItem> {
|
) -> Option<Self::ListItem> {
|
||||||
let colors = cx.theme().colors();
|
|
||||||
let Some(r#match) = self.matches.get(ix) else {
|
let Some(r#match) = self.matches.get(ix) else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
@ -304,23 +301,15 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
div()
|
ListItem::new(ix).selected(selected).child(
|
||||||
.px_1()
|
h_stack()
|
||||||
.text_color(colors.text)
|
.justify_between()
|
||||||
.text_ui()
|
.child(HighlightedLabel::new(
|
||||||
.bg(colors.ghost_element_background)
|
command.name.clone(),
|
||||||
.rounded_md()
|
r#match.positions.clone(),
|
||||||
.when(selected, |this| this.bg(colors.ghost_element_selected))
|
))
|
||||||
.hover(|this| this.bg(colors.ghost_element_hover))
|
.children(KeyBinding::for_action(&*command.action, cx)),
|
||||||
.child(
|
),
|
||||||
h_stack()
|
|
||||||
.justify_between()
|
|
||||||
.child(HighlightedLabel::new(
|
|
||||||
command.name.clone(),
|
|
||||||
r#match.positions.clone(),
|
|
||||||
))
|
|
||||||
.children(KeyBinding::for_action(&*command.action, cx)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,8 @@ use collections::HashMap;
|
||||||
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
||||||
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
actions, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model,
|
||||||
InteractiveElement, IntoElement, Model, ParentElement, Render, Styled, Task, View, ViewContext,
|
ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
|
||||||
VisualContext, WeakView,
|
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
||||||
|
@ -16,8 +15,7 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use text::Point;
|
use text::Point;
|
||||||
use theme::ActiveTheme;
|
use ui::{v_stack, HighlightedLabel, ListItem};
|
||||||
use ui::{v_stack, HighlightedLabel, StyledExt};
|
|
||||||
use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
|
use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
@ -530,7 +528,7 @@ impl FileFinderDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for FileFinderDelegate {
|
impl PickerDelegate for FileFinderDelegate {
|
||||||
type ListItem = Div;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Search project files...".into()
|
"Search project files...".into()
|
||||||
|
@ -716,26 +714,16 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
.matches
|
.matches
|
||||||
.get(ix)
|
.get(ix)
|
||||||
.expect("Invalid matches state: no element for index {ix}");
|
.expect("Invalid matches state: no element for index {ix}");
|
||||||
let theme = cx.theme();
|
|
||||||
let colors = theme.colors();
|
|
||||||
|
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
self.labels_for_match(path_match, cx, ix);
|
self.labels_for_match(path_match, cx, ix);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
div()
|
ListItem::new(ix).selected(selected).child(
|
||||||
.px_1()
|
v_stack()
|
||||||
.text_color(colors.text)
|
.child(HighlightedLabel::new(file_name, file_name_positions))
|
||||||
.text_ui()
|
.child(HighlightedLabel::new(full_path, full_path_positions)),
|
||||||
.bg(colors.ghost_element_background)
|
),
|
||||||
.rounded_md()
|
|
||||||
.when(selected, |this| this.bg(colors.ghost_element_selected))
|
|
||||||
.hover(|this| this.bg(colors.ghost_element_hover))
|
|
||||||
.child(
|
|
||||||
v_stack()
|
|
||||||
.child(HighlightedLabel::new(file_name, file_name_positions))
|
|
||||||
.child(HighlightedLabel::new(full_path, full_path_positions)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,23 +231,16 @@ impl RenderOnce for ListSubHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Copy, Clone)]
|
|
||||||
pub enum ListEntrySize {
|
|
||||||
#[default]
|
|
||||||
Small,
|
|
||||||
Medium,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct ListItem {
|
pub struct ListItem {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
|
selected: bool,
|
||||||
// TODO: Reintroduce this
|
// TODO: Reintroduce this
|
||||||
// disclosure_control_style: DisclosureControlVisibility,
|
// disclosure_control_style: DisclosureControlVisibility,
|
||||||
indent_level: u32,
|
indent_level: u32,
|
||||||
left_slot: Option<GraphicSlot>,
|
left_slot: Option<GraphicSlot>,
|
||||||
overflow: OverflowStyle,
|
overflow: OverflowStyle,
|
||||||
size: ListEntrySize,
|
|
||||||
toggle: Toggle,
|
toggle: Toggle,
|
||||||
variant: ListItemVariant,
|
variant: ListItemVariant,
|
||||||
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||||
|
@ -259,10 +252,10 @@ impl ListItem {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
selected: false,
|
||||||
indent_level: 0,
|
indent_level: 0,
|
||||||
left_slot: None,
|
left_slot: None,
|
||||||
overflow: OverflowStyle::Hidden,
|
overflow: OverflowStyle::Hidden,
|
||||||
size: ListEntrySize::default(),
|
|
||||||
toggle: Toggle::NotToggleable,
|
toggle: Toggle::NotToggleable,
|
||||||
variant: ListItemVariant::default(),
|
variant: ListItemVariant::default(),
|
||||||
on_click: Default::default(),
|
on_click: Default::default(),
|
||||||
|
@ -290,6 +283,11 @@ impl ListItem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn selected(mut self, selected: bool) -> Self {
|
||||||
|
self.selected = selected;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn left_content(mut self, left_content: GraphicSlot) -> Self {
|
pub fn left_content(mut self, left_content: GraphicSlot) -> Self {
|
||||||
self.left_slot = Some(left_content);
|
self.left_slot = Some(left_content);
|
||||||
self
|
self
|
||||||
|
@ -304,11 +302,6 @@ impl ListItem {
|
||||||
self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into()));
|
self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(mut self, size: ListEntrySize) -> Self {
|
|
||||||
self.size = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for ListItem {
|
impl RenderOnce for ListItem {
|
||||||
|
@ -328,10 +321,6 @@ impl RenderOnce for ListItem {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let sized_item = match self.size {
|
|
||||||
ListEntrySize::Small => div().h_6(),
|
|
||||||
ListEntrySize::Medium => div().h_7(),
|
|
||||||
};
|
|
||||||
div()
|
div()
|
||||||
.id(self.id)
|
.id(self.id)
|
||||||
.relative()
|
.relative()
|
||||||
|
@ -354,8 +343,11 @@ impl RenderOnce for ListItem {
|
||||||
// })
|
// })
|
||||||
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
||||||
.active(|style| style.bg(cx.theme().colors().ghost_element_active))
|
.active(|style| style.bg(cx.theme().colors().ghost_element_active))
|
||||||
|
.when(self.selected, |this| {
|
||||||
|
this.bg(cx.theme().colors().ghost_element_selected)
|
||||||
|
})
|
||||||
.child(
|
.child(
|
||||||
sized_item
|
div()
|
||||||
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
||||||
// .ml(rems(0.75 * self.indent_level as f32))
|
// .ml(rems(0.75 * self.indent_level as f32))
|
||||||
.children((0..self.indent_level).map(|_| {
|
.children((0..self.indent_level).map(|_| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue