use crossterm::style::Stylize;
use r3bl_core::{call_if_true, ch, ChUnit};
use crate::DEVELOPMENT_MODE;
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum CaretVerticalViewportLocation {
AtAbsoluteTop,
AboveTopOfViewport,
AtTopOfViewport,
InMiddleOfViewport,
AtBottomOfViewport,
BelowBottomOfViewport,
AtAbsoluteBottom,
NotFound,
}
pub fn get_scroll_adjusted_row_index(
raw_caret_row_index: ChUnit,
scroll_offset_row_index: ChUnit,
) -> ChUnit {
raw_caret_row_index + scroll_offset_row_index
}
pub fn locate_cursor_in_viewport(
raw_caret_row_index: ChUnit,
scroll_offset_row_index: ChUnit,
display_height: ChUnit,
items_size: ChUnit,
) -> CaretVerticalViewportLocation {
let abs_row_index =
get_scroll_adjusted_row_index(raw_caret_row_index, scroll_offset_row_index);
call_if_true!(DEVELOPMENT_MODE, {
tracing::debug!(
"locate_cursor_in_viewport(): raw_caret_row_index: {}, scroll_offset_row_index: {}, abs_row_index: {}, display_height: {}, items_size: {}",
format!("{raw_caret_row_index}").green(),
format!("{scroll_offset_row_index}").green(),
format!("{abs_row_index}").green(),
format!("{display_height}").green(),
format!("{items_size}").green()
);
});
if abs_row_index == items_size - 1 {
CaretVerticalViewportLocation::AtAbsoluteBottom
} else if abs_row_index == ch!(0) {
CaretVerticalViewportLocation::AtAbsoluteTop
} else if abs_row_index < scroll_offset_row_index {
CaretVerticalViewportLocation::AboveTopOfViewport
} else if abs_row_index == scroll_offset_row_index {
CaretVerticalViewportLocation::AtTopOfViewport
}
else if abs_row_index > scroll_offset_row_index
&& abs_row_index < (scroll_offset_row_index + display_height - 1)
{
CaretVerticalViewportLocation::InMiddleOfViewport
} else if abs_row_index == (scroll_offset_row_index + display_height - 1) {
CaretVerticalViewportLocation::AtBottomOfViewport
} else if abs_row_index > (scroll_offset_row_index + display_height - 1) {
CaretVerticalViewportLocation::BelowBottomOfViewport
} else {
CaretVerticalViewportLocation::NotFound
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn test_get_scroll_adjusted_row_index() {
assert_eq!(get_scroll_adjusted_row_index(ch!(0), ch!(0)), ch!(0));
assert_eq!(get_scroll_adjusted_row_index(ch!(1), ch!(0)), ch!(1));
assert_eq!(get_scroll_adjusted_row_index(ch!(0), ch!(1)), ch!(1));
assert_eq!(get_scroll_adjusted_row_index(ch!(2), ch!(3)), ch!(5));
}
#[test]
fn test_locate_cursor_in_viewport() {
assert_eq!(
locate_cursor_in_viewport(ch!(0), ch!(0), ch!(10), ch!(20)),
CaretVerticalViewportLocation::AtAbsoluteTop
);
assert_eq!(
locate_cursor_in_viewport(ch!(19), ch!(0), ch!(10), ch!(20)),
CaretVerticalViewportLocation::AtAbsoluteBottom
);
assert_eq!(
locate_cursor_in_viewport(ch!(5), ch!(0), ch!(10), ch!(20)),
CaretVerticalViewportLocation::InMiddleOfViewport
);
assert_eq!(
locate_cursor_in_viewport(ch!(0), ch!(5), ch!(10), ch!(20)),
CaretVerticalViewportLocation::AtTopOfViewport
);
assert_eq!(
locate_cursor_in_viewport(ch!(5), ch!(5), ch!(10), ch!(20)),
CaretVerticalViewportLocation::InMiddleOfViewport
);
assert_eq!(
locate_cursor_in_viewport(ch!(14), ch!(5), ch!(10), ch!(20)),
CaretVerticalViewportLocation::AtAbsoluteBottom
);
assert_eq!(
locate_cursor_in_viewport(ch!(15), ch!(5), ch!(10), ch!(20)),
CaretVerticalViewportLocation::BelowBottomOfViewport
);
assert_eq!(
locate_cursor_in_viewport(ch!(21), ch!(5), ch!(10), ch!(20)),
CaretVerticalViewportLocation::BelowBottomOfViewport
);
}
}