@@ -147,6 +147,7 @@ impl PickerDelegate for CommandPaletteDelegate {
type ListItem = Div<Picker<Self>>;
fn match_count(&self) -> usize {
+ dbg!(self.matches.len());
self.matches.len()
}
@@ -163,44 +164,11 @@ impl PickerDelegate for CommandPaletteDelegate {
query: String,
cx: &mut ViewContext<Picker<Self>>,
) -> gpui::Task<()> {
- let view_id = &self.previous_focus_handle;
- let window = cx.window();
- cx.spawn(move |picker, mut cx| async move {
- let mut actions = picker
- .update(&mut cx, |this, _| this.delegate.commands.clone())
- .expect("todo: handle picker no longer being around");
- // _ = window
- // .available_actions(view_id, &cx)
- // .into_iter()
- // .flatten()
- // .filter_map(|(name, action, bindings)| {
- // let filtered = cx.read(|cx| {
- // if cx.has_global::<CommandPaletteFilter>() {
- // let filter = cx.global::<CommandPaletteFilter>();
- // filter.filtered_namespaces.contains(action.namespace())
- // } else {
- // false
- // }
- // });
-
- // if filtered {
- // None
- // } else {
- // Some(Command {
- // name: humanize_action_name(name),
- // action,
- // keystrokes: bindings
- // .iter()
- // .map(|binding| binding.keystrokes())
- // .last()
- // .map_or(Vec::new(), |keystrokes| keystrokes.to_vec()),
- // })
- // }
- // })
- // .collect::<Vec<_>>();
+ let mut commands = self.commands.clone();
+ cx.spawn(move |picker, mut cx| async move {
cx.read_global::<HitCounts, _>(|hit_counts, _| {
- actions.sort_by_key(|action| {
+ commands.sort_by_key(|action| {
(
Reverse(hit_counts.0.get(&action.name).cloned()),
action.name.clone(),
@@ -209,7 +177,7 @@ impl PickerDelegate for CommandPaletteDelegate {
})
.ok();
- let candidates = actions
+ let candidates = commands
.iter()
.enumerate()
.map(|(ix, command)| StringMatchCandidate {
@@ -240,15 +208,13 @@ impl PickerDelegate for CommandPaletteDelegate {
)
.await
};
- let mut intercept_result = None;
- // todo!() for vim mode
- // cx.read(|cx| {
- // if cx.has_global::<CommandPaletteInterceptor>() {
- // cx.global::<CommandPaletteInterceptor>()(&query, cx)
- // } else {
- // None
- // }
- // });
+
+ let mut intercept_result = cx
+ .try_read_global(|interceptor: &CommandPaletteInterceptor, cx| {
+ (interceptor)(&query, cx)
+ })
+ .flatten();
+
if *RELEASE_CHANNEL == ReleaseChannel::Dev {
if parse_zed_link(&query).is_some() {
intercept_result = Some(CommandInterceptResult {
@@ -266,11 +232,11 @@ impl PickerDelegate for CommandPaletteDelegate {
{
if let Some(idx) = matches
.iter()
- .position(|m| actions[m.candidate_id].action.type_id() == action.type_id())
+ .position(|m| commands[m.candidate_id].action.type_id() == action.type_id())
{
matches.remove(idx);
}
- actions.push(Command {
+ commands.push(Command {
name: string.clone(),
action,
keystrokes: vec![],
@@ -278,7 +244,7 @@ impl PickerDelegate for CommandPaletteDelegate {
matches.insert(
0,
StringMatch {
- candidate_id: actions.len() - 1,
+ candidate_id: commands.len() - 1,
string,
positions,
score: 0.0,
@@ -288,7 +254,8 @@ impl PickerDelegate for CommandPaletteDelegate {
picker
.update(&mut cx, |picker, _| {
let delegate = &mut picker.delegate;
- delegate.commands = actions;
+ dbg!(&matches);
+ delegate.commands = commands;
delegate.matches = matches;
if delegate.matches.is_empty() {
delegate.selected_ix = 0;
@@ -1,6 +1,6 @@
use crate::{
- point, px, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, ElementId,
- ElementInteractivity, InteractiveElementState, LayoutId, Pixels, Point, Size,
+ point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element,
+ ElementId, ElementInteractivity, InteractiveElementState, LayoutId, Pixels, Point, Size,
StatefulInteractive, StatefulInteractivity, StatelessInteractive, StatelessInteractivity,
StyleRefinement, Styled, ViewContext,
};
@@ -86,8 +86,14 @@ impl<V: 'static> Styled for UniformList<V> {
}
}
+#[derive(Default)]
+pub struct UniformListState {
+ interactive: InteractiveElementState,
+ item_size: Size<Pixels>,
+}
+
impl<V: 'static> Element<V> for UniformList<V> {
- type ElementState = InteractiveElementState;
+ type ElementState = UniformListState;
fn id(&self) -> Option<crate::ElementId> {
Some(self.id.clone())
@@ -95,20 +101,49 @@ impl<V: 'static> Element<V> for UniformList<V> {
fn initialize(
&mut self,
- _: &mut V,
+ view_state: &mut V,
element_state: Option<Self::ElementState>,
- _: &mut ViewContext<V>,
+ cx: &mut ViewContext<V>,
) -> Self::ElementState {
- element_state.unwrap_or_default()
+ element_state.unwrap_or_else(|| {
+ let item_size = self.measure_first_item(view_state, None, cx);
+ UniformListState {
+ interactive: InteractiveElementState::default(),
+ item_size,
+ }
+ })
}
fn layout(
&mut self,
_view_state: &mut V,
- _element_state: &mut Self::ElementState,
+ element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
- cx.request_layout(&self.computed_style(), None)
+ let max_items = self.item_count;
+ let item_size = element_state.item_size;
+ let rem_size = cx.rem_size();
+ cx.request_measured_layout(
+ self.computed_style(),
+ rem_size,
+ move |known_dimensions: Size<Option<Pixels>>, available_space: Size<AvailableSpace>| {
+ let desired_height = item_size.height * max_items;
+ let width = known_dimensions
+ .width
+ .unwrap_or(match available_space.width {
+ AvailableSpace::Definite(x) => x,
+ AvailableSpace::MinContent => item_size.width,
+ AvailableSpace::MaxContent => item_size.width,
+ });
+ let height = match available_space.height {
+ AvailableSpace::Definite(x) => desired_height.min(x),
+ AvailableSpace::MinContent => desired_height,
+ AvailableSpace::MaxContent => desired_height,
+ };
+ dbg!(known_dimensions, available_space, size(width, height));
+ size(width, height)
+ },
+ )
}
fn paint(
@@ -133,12 +168,15 @@ impl<V: 'static> Element<V> for UniformList<V> {
cx.with_z_index(style.z_index.unwrap_or(0), |cx| {
let content_size;
if self.item_count > 0 {
- let item_height = self.measure_item_height(view_state, padded_bounds, cx);
+ let item_height = self
+ .measure_first_item(view_state, Some(padded_bounds.size.width), cx)
+ .height;
+ dbg!(item_height, padded_bounds);
if let Some(scroll_handle) = self.scroll_handle.clone() {
scroll_handle.0.lock().replace(ScrollHandleState {
item_height,
list_height: padded_bounds.size.height,
- scroll_offset: element_state.track_scroll_offset(),
+ scroll_offset: element_state.interactive.track_scroll_offset(),
});
}
let visible_item_count = if item_height > px(0.) {
@@ -146,7 +184,9 @@ impl<V: 'static> Element<V> for UniformList<V> {
} else {
0
};
+ dbg!(visible_item_count);
let scroll_offset = element_state
+ .interactive
.scroll_offset()
.map_or((0.0).into(), |offset| offset.y);
let first_visible_element_ix = (-scroll_offset / item_height).floor() as usize;
@@ -190,20 +230,25 @@ impl<V: 'static> Element<V> for UniformList<V> {
let overflow = point(style.overflow.x, Overflow::Scroll);
cx.with_z_index(0, |cx| {
- self.interactivity
- .paint(bounds, content_size, overflow, element_state, cx);
+ self.interactivity.paint(
+ bounds,
+ content_size,
+ overflow,
+ &mut element_state.interactive,
+ cx,
+ );
});
})
}
}
impl<V> UniformList<V> {
- fn measure_item_height(
+ fn measure_first_item(
&self,
view_state: &mut V,
- list_bounds: Bounds<Pixels>,
+ list_width: Option<Pixels>,
cx: &mut ViewContext<V>,
- ) -> Pixels {
+ ) -> Size<Pixels> {
let mut items = (self.render_items)(view_state, 0..1, cx);
debug_assert!(items.len() == 1);
let mut item_to_measure = items.pop().unwrap();
@@ -212,11 +257,13 @@ impl<V> UniformList<V> {
cx.compute_layout(
layout_id,
Size {
- width: AvailableSpace::Definite(list_bounds.size.width),
+ width: list_width.map_or(AvailableSpace::MinContent, |width| {
+ AvailableSpace::Definite(width)
+ }),
height: AvailableSpace::MinContent,
},
);
- cx.layout_bounds(layout_id).size.height
+ cx.layout_bounds(layout_id).size
}
pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self {