Derive autocomplete menu's width from the width of its largest item
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
1a6e972ed4
commit
c19d639e0a
5 changed files with 98 additions and 39 deletions
|
@ -51,6 +51,7 @@ where
|
|||
append_items: F,
|
||||
padding_top: f32,
|
||||
padding_bottom: f32,
|
||||
get_width_from_item: Option<usize>,
|
||||
}
|
||||
|
||||
impl<F> UniformList<F>
|
||||
|
@ -64,9 +65,15 @@ where
|
|||
append_items,
|
||||
padding_top: 0.,
|
||||
padding_bottom: 0.,
|
||||
get_width_from_item: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_width_from_item(mut self, item_ix: Option<usize>) -> Self {
|
||||
self.get_width_from_item = item_ix;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_padding_top(mut self, padding: f32) -> Self {
|
||||
self.padding_top = padding;
|
||||
self
|
||||
|
@ -155,46 +162,70 @@ where
|
|||
"UniformList does not support being rendered with an unconstrained height"
|
||||
);
|
||||
}
|
||||
let mut size = constraint.max;
|
||||
let mut item_constraint =
|
||||
SizeConstraint::new(vec2f(size.x(), 0.0), vec2f(size.x(), f32::INFINITY));
|
||||
let mut item_height = 0.;
|
||||
let mut scroll_max = 0.;
|
||||
|
||||
let mut items = Vec::new();
|
||||
(self.append_items)(0..1, &mut items, cx);
|
||||
if let Some(first_item) = items.first_mut() {
|
||||
let mut item_size = first_item.layout(item_constraint, cx);
|
||||
item_size.set_x(size.x());
|
||||
item_constraint.min = item_size;
|
||||
item_constraint.max = item_size;
|
||||
item_height = item_size.y();
|
||||
|
||||
let scroll_height = self.item_count as f32 * item_height;
|
||||
if scroll_height < size.y() {
|
||||
size.set_y(size.y().min(scroll_height).max(constraint.min.y()));
|
||||
}
|
||||
|
||||
let scroll_height =
|
||||
item_height * self.item_count as f32 + self.padding_top + self.padding_bottom;
|
||||
scroll_max = (scroll_height - size.y()).max(0.);
|
||||
self.autoscroll(scroll_max, size.y(), item_height);
|
||||
|
||||
items.clear();
|
||||
let start = cmp::min(
|
||||
((self.scroll_top() - self.padding_top) / item_height) as usize,
|
||||
self.item_count,
|
||||
if self.item_count == 0 {
|
||||
return (
|
||||
constraint.min,
|
||||
LayoutState {
|
||||
item_height: 0.,
|
||||
scroll_max: 0.,
|
||||
items,
|
||||
},
|
||||
);
|
||||
let end = cmp::min(
|
||||
self.item_count,
|
||||
start + (size.y() / item_height).ceil() as usize + 1,
|
||||
);
|
||||
(self.append_items)(start..end, &mut items, cx);
|
||||
for item in &mut items {
|
||||
item.layout(item_constraint, cx);
|
||||
}
|
||||
}
|
||||
|
||||
let mut size = constraint.max;
|
||||
let mut item_size;
|
||||
if let Some(sample_item_ix) = self.get_width_from_item {
|
||||
(self.append_items)(sample_item_ix..sample_item_ix + 1, &mut items, cx);
|
||||
let sample_item = items.get_mut(0).unwrap();
|
||||
item_size = sample_item.layout(constraint, cx);
|
||||
size.set_x(item_size.x());
|
||||
} else {
|
||||
size = constraint.min;
|
||||
(self.append_items)(0..1, &mut items, cx);
|
||||
let first_item = items.first_mut().unwrap();
|
||||
item_size = first_item.layout(
|
||||
SizeConstraint::new(
|
||||
vec2f(constraint.max.x(), 0.0),
|
||||
vec2f(constraint.max.x(), f32::INFINITY),
|
||||
),
|
||||
cx,
|
||||
);
|
||||
item_size.set_x(size.x());
|
||||
}
|
||||
|
||||
let item_constraint = SizeConstraint {
|
||||
min: item_size,
|
||||
max: vec2f(constraint.max.x(), item_size.y()),
|
||||
};
|
||||
let item_height = item_size.y();
|
||||
|
||||
let scroll_height = self.item_count as f32 * item_height;
|
||||
if scroll_height < size.y() {
|
||||
size.set_y(size.y().min(scroll_height).max(constraint.min.y()));
|
||||
}
|
||||
|
||||
let scroll_height =
|
||||
item_height * self.item_count as f32 + self.padding_top + self.padding_bottom;
|
||||
let scroll_max = (scroll_height - size.y()).max(0.);
|
||||
self.autoscroll(scroll_max, size.y(), item_height);
|
||||
|
||||
let start = cmp::min(
|
||||
((self.scroll_top() - self.padding_top) / item_height) as usize,
|
||||
self.item_count,
|
||||
);
|
||||
let end = cmp::min(
|
||||
self.item_count,
|
||||
start + (size.y() / item_height).ceil() as usize + 1,
|
||||
);
|
||||
items.clear();
|
||||
(self.append_items)(start..end, &mut items, cx);
|
||||
for item in &mut items {
|
||||
let item_size = item.layout(item_constraint, cx);
|
||||
if item_size.x() > size.x() {
|
||||
size.set_x(item_size.x());
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue