use r3bl_ansi_color::AnsiStyledText;
use r3bl_core::{ChUnit, Size};
use crate::{get_scroll_adjusted_row_index,
locate_cursor_in_viewport,
CalculateResizeHint,
CaretVerticalViewportLocation,
SelectionMode};
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct State<'a> {
pub max_display_height: ChUnit,
pub max_display_width: ChUnit,
pub raw_caret_row_index: ChUnit,
pub scroll_offset_row_index: ChUnit,
pub items: Vec<String>,
pub selected_items: Vec<String>,
pub header: String,
pub multi_line_header: Vec<Vec<AnsiStyledText<'a>>>,
pub selection_mode: SelectionMode,
pub resize_hint: Option<ResizeHint>,
pub window_size: Option<Size>,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Header {
Single,
Multiple,
}
impl State<'_> {
pub fn get_header(&self) -> Header {
match self.multi_line_header.is_empty() {
true => Header::Single,
false => Header::Multiple,
}
}
}
#[cfg(test)]
mod tests {
use r3bl_core::assert_eq2;
use super::*;
#[test]
fn test_header_enum() {
let mut state = State {
multi_line_header: vec![vec![AnsiStyledText {
text: "line1",
style: &[],
}]],
..Default::default()
};
let lhs = state.get_header();
let rhs = Header::Multiple;
assert_eq2!(lhs, rhs);
state.multi_line_header = vec![];
assert_eq2!(state.get_header(), Header::Single);
}
}
impl CalculateResizeHint for State<'_> {
fn set_size(&mut self, new_size: Size) {
self.window_size = Some(new_size);
self.clear_resize_hint();
}
fn get_resize_hint(&self) -> Option<ResizeHint> { self.resize_hint.clone() }
fn set_resize_hint(&mut self, new_size: Size) {
self.resize_hint = if let Some(old_size) = self.window_size {
if new_size != old_size {
if (new_size.col_count > old_size.col_count)
|| (new_size.row_count > old_size.row_count)
{
Some(ResizeHint::GotBigger)
} else if (new_size.col_count < old_size.col_count)
|| (new_size.row_count < old_size.row_count)
{
Some(ResizeHint::GotSmaller)
} else {
Some(ResizeHint::NoChange)
}
} else {
None
}
} else {
None
};
if self.window_size.is_some() {
self.set_size(new_size)
}
}
fn clear_resize_hint(&mut self) { self.resize_hint = None; }
}
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
pub enum ResizeHint {
GotBigger,
GotSmaller,
#[default]
NoChange,
}
impl State<'_> {
pub fn get_focused_index(&self) -> ChUnit {
get_scroll_adjusted_row_index(
self.raw_caret_row_index,
self.scroll_offset_row_index,
)
}
pub fn locate_cursor_in_viewport(&self) -> CaretVerticalViewportLocation {
locate_cursor_in_viewport(
self.raw_caret_row_index,
self.scroll_offset_row_index,
self.max_display_height,
self.items.len().into(),
)
}
}