#[derive(Debug, Clone, PartialEq)]
pub struct VirtualWindow {
pub first_visible: usize,
pub last_visible: usize,
pub offset_before: f32,
pub offset_after: f32,
}
pub fn compute_virtual_list_window(
total_rows: usize,
row_height: f32,
viewport_y: f32,
viewport_height: f32,
overscan: usize,
) -> VirtualWindow {
if total_rows == 0 || row_height <= 0.0 {
return VirtualWindow {
first_visible: 0,
last_visible: 0,
offset_before: 0.0,
offset_after: 0.0,
};
}
let visible_rows = (viewport_height / row_height).ceil() as usize;
let first = (viewport_y / row_height).floor() as isize - overscan as isize;
let first = first.max(0) as usize;
let last = first + visible_rows + 2 * overscan;
let last = last.min(total_rows);
VirtualWindow {
first_visible: first,
last_visible: last,
offset_before: first as f32 * row_height,
offset_after: (total_rows - last) as f32 * row_height,
}
}
pub fn compute_virtual_list_window_variable(
prefix_heights: &[f32],
viewport_y: f32,
viewport_height: f32,
overscan: usize,
) -> VirtualWindow {
let total_rows = prefix_heights.len().saturating_sub(1);
if total_rows == 0 {
return VirtualWindow {
first_visible: 0,
last_visible: 0,
offset_before: 0.0,
offset_after: 0.0,
};
}
let first_idx = prefix_heights
.partition_point(|&h| h < viewport_y)
.saturating_sub(1);
let first = first_idx.saturating_sub(overscan);
let viewport_bottom = viewport_y + viewport_height;
let last_idx = prefix_heights.partition_point(|&h| h < viewport_bottom);
let last = (last_idx + overscan).min(total_rows);
VirtualWindow {
first_visible: first,
last_visible: last,
offset_before: prefix_heights[first],
offset_after: prefix_heights[total_rows] - prefix_heights[last],
}
}