use super::{Overflow, Row, Sidebar, section_header_row};
use unicode_width::UnicodeWidthStr;
impl Sidebar {
pub(super) fn rows(&self) -> Vec<Row<'_>> {
let mut rows = Vec::new();
for section in &self.sections {
let mut header_shown = false;
for item in section.items.iter().filter(|item| self.matches(item)) {
if !header_shown {
if !section.title.is_empty() {
rows.push(Row::Header(§ion.title));
}
header_shown = true;
}
rows.push(Row::Item(item));
}
}
rows
}
pub(super) fn selected_row(&self, rows: &[Row]) -> usize {
let mut item_index = 0;
for (row_index, row) in rows.iter().enumerate() {
if let Row::Item(_) = row {
if item_index == self.selected {
return row_index;
}
item_index += 1;
}
}
0
}
pub(super) fn scroll_offset(
&self,
rows: &[Row],
selected_row: usize,
height: usize,
) -> usize {
if height == 0 || rows.is_empty() {
return 0;
}
let max_offset = rows.len().saturating_sub(height);
let anchor = section_header_row(rows, selected_row);
let mut offset = self.offset.get().min(max_offset);
if anchor < offset {
offset = anchor;
}
if selected_row >= offset + height {
offset = selected_row + 1 - height;
}
offset.min(max_offset)
}
pub(super) fn clamp_h_offset(
&self,
max_width: usize,
inner_width: usize,
) -> usize {
if self.overflow != Overflow::Scroll {
return 0;
}
let max_offset = max_width.saturating_sub(inner_width);
let clamped = self.h_offset.get().min(max_offset);
self.h_offset.set(clamped);
clamped
}
pub(super) fn row_width(row: &Row) -> usize {
match row {
Row::Header(title) => title.width(),
Row::Item(item) => item.label.width() + 2,
}
}
}