66 lines
1.6 KiB
Rust
66 lines
1.6 KiB
Rust
|
|
trait ListContentProvider<Item> {
|
|
|
|
/// Get the number of items provided
|
|
fn get_count(&self) -> i64;
|
|
|
|
fn get_item(&self, index: i64) -> Item;
|
|
}
|
|
|
|
trait ListLabelProvider<Item> {
|
|
|
|
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<Item>,
|
|
label_provider: &'a dyn ListLabelProvider<Item>,
|
|
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<Item>, label_provider: &'a dyn ListLabelProvider<Item>) -> 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();
|
|
}
|
|
|
|
}
|