trait ListContentProvider { /// Get the number of items provided fn get_count(&self) -> i64; fn get_item(&self, index: i64) -> Item; } trait ListLabelProvider { fn get_label(&self, item: &Item) -> str; } trait CellRenderer { fn new() -> Self; /// Get the height of a single cell fn height(&self) -> i64; } struct ListView<'a, Item, R: CellRenderer> { content_provider: &'a dyn ListContentProvider, label_provider: &'a dyn ListLabelProvider, cell_renderer: R, x: i64, } /// A ListView is responsible for: /// - get number of objects from the content provider /// - manage the range of visible objects /// - retrieve objects to be rendered from the content provider /// impl<'a, Item, R: CellRenderer> ListView<'a, Item, R> { pub fn new(content_provider: &'a dyn ListContentProvider, label_provider: &'a dyn ListLabelProvider) -> Self { ListView::<'a, Item, R> { content_provider, label_provider, cell_renderer: CellRenderer::new(), x: 0, } } pub fn refresh(&mut self) { let list_height = self.content_provider.get_count() * self.cell_renderer.height(); if self.x > list_height { self.x = list_height; } } pub fn top_item(&self) -> Item { let index = self.x / self.cell_renderer.height(); self.content_provider.get_item(index) } /// move the viewport on the list by the given amount pub fn move_by(&mut self, delta: i64) { self.x += delta; self.refresh(); } }