#![allow(deprecated)]
use std::collections::HashMap;
use crate::{ListState, PreRender, PreRenderContext, ScrollAxis};
pub(crate) fn layout_on_viewport<T: PreRender>(
state: &mut ListState,
widgets: &mut [T],
total_main_axis_size: u16,
cross_axis_size: u16,
scroll_axis: ScrollAxis,
) -> Vec<ViewportLayout> {
let mut viewport_layouts: Vec<ViewportLayout> = Vec::new();
let selected = state.selected.unwrap_or(0);
if selected < state.view_state.offset {
state.view_state.offset = selected;
}
let mut main_axis_size_cache: HashMap<usize, u16> = HashMap::new();
let (mut y, mut index) = (0, state.view_state.offset);
let mut found = false;
for widget in widgets.iter_mut().skip(state.view_state.offset) {
let is_selected = state.selected == Some(index);
let context = PreRenderContext::new(is_selected, cross_axis_size, scroll_axis, index);
let main_axis_size = widget.pre_render(&context);
main_axis_size_cache.insert(index, main_axis_size);
if y + main_axis_size > total_main_axis_size {
let dy = total_main_axis_size - y;
if dy > 0 {
viewport_layouts.push(ViewportLayout {
main_axis_size: dy,
truncated_by: main_axis_size.saturating_sub(dy),
});
}
break;
}
if selected == index {
found = true;
}
y += main_axis_size;
index += 1;
viewport_layouts.push(ViewportLayout {
main_axis_size,
truncated_by: 0,
});
}
if found {
return viewport_layouts;
}
viewport_layouts.clear();
let (mut y, mut index) = (0, selected);
let last = widgets.len().saturating_sub(1);
for widget in widgets.iter_mut().rev().skip(last.saturating_sub(selected)) {
let main_axis_size = if let Some(main_axis_size) = main_axis_size_cache.remove(&index) {
main_axis_size
} else {
let is_selected = state.selected == Some(index);
let context = PreRenderContext::new(is_selected, cross_axis_size, scroll_axis, index);
widget.pre_render(&context)
};
if y + main_axis_size >= total_main_axis_size {
let dy = total_main_axis_size - y;
viewport_layouts.insert(
0,
ViewportLayout {
main_axis_size: dy,
truncated_by: main_axis_size.saturating_sub(dy),
},
);
state.view_state.offset = index;
break;
}
viewport_layouts.insert(
0,
ViewportLayout {
main_axis_size,
truncated_by: 0,
},
);
y += main_axis_size;
index -= 1;
}
viewport_layouts
}
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)]
pub(crate) struct ViewportLayout {
pub(crate) main_axis_size: u16,
pub(crate) truncated_by: u16,
}