use std::rc::Rc;
use gpui::prelude::*;
use gpui::{px, uniform_list, AnyElement, App, ElementId, IntoElement, Window};
type ItemBuilder = Rc<dyn Fn(usize, &mut Window, &mut App) -> AnyElement + 'static>;
#[derive(IntoElement)]
pub struct VirtualList {
id: ElementId,
count: usize,
height: f32,
item: ItemBuilder,
}
impl VirtualList {
pub fn new<E>(
id: impl Into<ElementId>,
count: usize,
item: impl Fn(usize, &mut Window, &mut App) -> E + 'static,
) -> Self
where
E: IntoElement,
{
VirtualList {
id: id.into(),
count,
height: 240.0,
item: Rc::new(move |ix, window, cx| item(ix, window, cx).into_any_element()),
}
}
pub fn height(mut self, height: f32) -> Self {
self.height = height.max(0.0);
self
}
}
impl RenderOnce for VirtualList {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let item = self.item;
uniform_list(self.id, self.count, move |range, window, cx| {
range.map(|ix| item(ix, window, cx)).collect::<Vec<_>>()
})
.h(px(self.height))
.w_full()
}
}