use super::UiPicker;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(in crate::tui) enum OverlayFocus {
#[default]
Nav,
Detail,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(in crate::tui) enum OverlayScrollbarDrag {
Nav(super::super::scrollbar::HistoryScrollbarDrag),
Detail(super::super::scrollbar::HistoryScrollbarDrag),
}
impl UiPicker {
pub(in crate::tui) fn has_scrollable_detail(&self) -> bool {
self.is_overlay() && self.has_item_details()
}
pub(in crate::tui) fn focus_overlay_pane(&mut self, focus: OverlayFocus) {
self.overlay_focus = focus;
}
pub(in crate::tui) fn detail_pane_focused(&self) -> bool {
self.has_scrollable_detail() && self.overlay_focus == OverlayFocus::Detail
}
pub(in crate::tui) fn nav_window_start(&self, viewport_rows: usize) -> usize {
let matching = self.matching_indices();
let total = super::super::picker_rows::picker_row_count(&self.items, &matching);
let viewport_rows = viewport_rows.max(1);
let max_start = total.saturating_sub(viewport_rows);
let base = self.nav_scroll.min(max_start);
if !self.nav_follows_selection {
return base;
}
let selected_row =
super::super::picker_rows::selected_row_index(&self.items, &matching, self.selected);
let lowest = super::super::picker_rows::scroll_window_start(selected_row, viewport_rows);
let highest = selected_row.min(max_start);
base.clamp(lowest.min(highest), highest)
}
pub(in crate::tui) fn scroll_nav_by(&mut self, delta: isize, viewport_rows: usize) {
let current = self.nav_window_start(viewport_rows);
let max_start = {
let matching = self.matching_indices();
super::super::picker_rows::picker_row_count(&self.items, &matching)
.saturating_sub(viewport_rows.max(1))
};
self.nav_scroll = current.saturating_add_signed(delta).min(max_start);
self.nav_follows_selection = false;
}
pub(in crate::tui) fn scroll_nav_to(&mut self, top_line: usize, viewport_rows: usize) {
let max_start = {
let matching = self.matching_indices();
super::super::picker_rows::picker_row_count(&self.items, &matching)
.saturating_sub(viewport_rows.max(1))
};
self.nav_scroll = top_line.min(max_start);
self.nav_follows_selection = false;
}
pub(in crate::tui) fn overlay_scrollbar_drag(&self) -> Option<OverlayScrollbarDrag> {
self.overlay_scrollbar_drag
}
pub(in crate::tui) fn set_overlay_scrollbar_drag(
&mut self,
drag: Option<OverlayScrollbarDrag>,
) {
self.overlay_scrollbar_drag = drag;
}
pub(in crate::tui) fn hovered_nav_row(&self) -> Option<usize> {
self.hovered_nav_row
}
pub(in crate::tui) fn set_hovered_nav_row(&mut self, row_index: Option<usize>) {
self.hovered_nav_row = row_index;
}
pub(in crate::tui) fn nav_item_at_row(&self, row_index: usize) -> Option<usize> {
let matching = self.matching_indices();
super::super::picker_rows::item_index_at_row(&self.items, &matching, row_index)
}
pub(in crate::tui) fn select_nav_row(
&mut self,
row_index: usize,
viewport_rows: usize,
) -> bool {
let Some(index) = self.nav_item_at_row(row_index) else {
return false;
};
self.nav_scroll = self.nav_window_start(viewport_rows);
self.nav_follows_selection = true;
if index != self.selected {
self.selected = index;
self.on_selection_changed();
}
true
}
pub(in crate::tui) fn overlay_sizing(
&self,
) -> super::super::picker_overlay_layout::OverlaySizing {
super::super::picker_overlay_layout::OverlaySizing {
has_details: self.has_item_details(),
nav_rows: super::super::picker_rows::rows(&self.items, 0..self.items.len()).count(),
}
}
}