Allow measuring arbitrary items in UniformList

This commit is contained in:
Antonio Scandurra 2023-11-10 15:57:48 +01:00
parent c44db3b7ec
commit 468a014bfc
2 changed files with 23 additions and 77 deletions

View file

@ -1605,6 +1605,13 @@ impl CodeActionsMenu {
.bg(cx.theme().colors().element_background)
.px_2()
.py_1()
.with_width_from_item(
self.actions
.iter()
.enumerate()
.max_by_key(|(_, action)| action.lsp_action.title.chars().count())
.map(|(ix, _)| ix),
)
.render();
if self.deployed_from_indicator {
@ -1613,78 +1620,6 @@ impl CodeActionsMenu {
(cursor_position, element)
}
// enum ActionTag {}
// let container_style = style.autocomplete.container;
// let actions = self.actions.clone();
// let selected_item = self.selected_item;
// let element = UniformList::new(
// self.list.clone(),
// actions.len(),
// cx,
// move |_, range, items, cx| {
// let start_ix = range.start;
// for (ix, action) in actions[range].iter().enumerate() {
// let item_ix = start_ix + ix;
// items.push(
// MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
// let item_style = if item_ix == selected_item {
// style.autocomplete.selected_item
// } else if state.hovered() {
// style.autocomplete.hovered_item
// } else {
// style.autocomplete.item
// };
// Text::new(action.lsp_action.title.clone(), style.text.clone())
// .with_soft_wrap(false)
// .contained()
// .with_style(item_style)
// })
// .with_cursor_style(CursorStyle::PointingHand)
// .on_down(MouseButton::Left, move |_, this, cx| {
// let workspace = this
// .workspace
// .as_ref()
// .and_then(|(workspace, _)| workspace.upgrade(cx));
// cx.window_context().defer(move |cx| {
// if let Some(workspace) = workspace {
// workspace.update(cx, |workspace, cx| {
// if let Some(task) = Editor::confirm_code_action(
// workspace,
// &ConfirmCodeAction {
// item_ix: Some(item_ix),
// },
// cx,
// ) {
// task.detach_and_log_err(cx);
// }
// });
// }
// });
// })
// .into_any(),
// );
// }
// },
// )
// .with_width_from_item(
// self.actions
// .iter()
// .enumerate()
// .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
// .map(|(ix, _)| ix),
// )
// .contained()
// .with_style(container_style)
// .into_any();
// if self.deployed_from_indicator {
// *cursor_position.column_mut() = 0;
// }
// (cursor_position, element)
// }
}
pub struct CopilotState {

View file

@ -30,6 +30,7 @@ where
id: id.clone(),
style,
item_count,
item_to_measure_index: 0,
render_items: Box::new(move |view, visible_range, cx| {
f(view, visible_range, cx)
.into_iter()
@ -45,6 +46,7 @@ pub struct UniformList<V: 'static> {
id: ElementId,
style: StyleRefinement,
item_count: usize,
item_to_measure_index: usize,
render_items: Box<
dyn for<'a> Fn(
&'a mut V,
@ -112,7 +114,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
cx: &mut ViewContext<V>,
) -> Self::ElementState {
element_state.unwrap_or_else(|| {
let item_size = self.measure_first_item(view_state, None, cx);
let item_size = self.measure_item(view_state, None, cx);
UniformListState {
interactive: InteractiveElementState::default(),
item_size,
@ -174,7 +176,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
let content_size;
if self.item_count > 0 {
let item_height = self
.measure_first_item(view_state, Some(padded_bounds.size.width), cx)
.measure_item(view_state, Some(padded_bounds.size.width), cx)
.height;
if let Some(scroll_handle) = self.scroll_handle.clone() {
scroll_handle.0.lock().replace(ScrollHandleState {
@ -240,14 +242,23 @@ impl<V: 'static> Element<V> for UniformList<V> {
}
impl<V> UniformList<V> {
fn measure_first_item(
pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self {
self.item_to_measure_index = item_index.unwrap_or(0);
self
}
fn measure_item(
&self,
view_state: &mut V,
list_width: Option<Pixels>,
cx: &mut ViewContext<V>,
) -> Size<Pixels> {
let mut items = (self.render_items)(view_state, 0..1, cx);
debug_assert_eq!(items.len(), 1);
if self.item_count == 0 {
return Size::default();
}
let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1);
let mut items = (self.render_items)(view_state, item_ix..item_ix + 1, cx);
let mut item_to_measure = items.pop().unwrap();
let available_space = size(
list_width.map_or(AvailableSpace::MinContent, |width| {