use ratatui::{
layout::Rect,
style::{Color, Modifier, Style},
Frame,
};
use tracing::{debug, trace};
#[derive(Debug, Clone, Default)]
pub struct CrosshairPosition {
pub row: usize,
pub column: usize,
pub visible: bool,
}
pub struct CrosshairWidget {
position: CrosshairPosition,
style: Style,
}
impl Default for CrosshairWidget {
fn default() -> Self {
Self::new()
}
}
impl CrosshairWidget {
#[must_use]
pub fn new() -> Self {
Self {
position: CrosshairPosition::default(),
style: Style::default()
.bg(Color::DarkGray)
.add_modifier(Modifier::REVERSED),
}
}
pub fn set_position(&mut self, row: usize, column: usize) {
self.position.row = row;
self.position.column = column;
self.position.visible = true;
debug!("Crosshair position updated to ({}, {})", row, column);
}
pub fn hide(&mut self) {
self.position.visible = false;
}
pub fn show(&mut self) {
self.position.visible = true;
}
#[must_use]
pub fn position(&self) -> &CrosshairPosition {
&self.position
}
pub fn set_style(&mut self, style: Style) {
self.style = style;
}
pub fn render_overlay(
&self,
_f: &mut Frame,
table_area: Rect,
viewport_row_offset: usize,
viewport_col_offset: usize,
row_heights: &[u16], col_widths: &[u16], ) {
if !self.position.visible {
return;
}
let visible_rows = row_heights.len();
let visible_cols = col_widths.len();
if self.position.row < viewport_row_offset {
return; }
let relative_row = self.position.row - viewport_row_offset;
if relative_row >= visible_rows {
return; }
if self.position.column < viewport_col_offset {
return; }
let relative_col = self.position.column - viewport_col_offset;
if relative_col >= visible_cols {
return; }
let mut y = table_area.y + 2; for i in 0..relative_row {
y += row_heights[i];
}
let mut x = table_area.x + 1; for i in 0..relative_col {
x += col_widths[i] + 1; }
let cell_width = col_widths[relative_col];
let _cell_rect = Rect {
x,
y,
width: cell_width,
height: 1,
};
trace!(
"Rendering crosshair at viewport ({}, {}) -> screen ({}, {})",
relative_row,
relative_col,
x,
y
);
}
#[must_use]
pub fn calculate_scroll_offset(
&self,
current_row_offset: usize,
current_col_offset: usize,
viewport_height: usize,
viewport_width: usize,
) -> (usize, usize) {
let mut new_row_offset = current_row_offset;
let mut new_col_offset = current_col_offset;
if self.position.row < current_row_offset {
new_row_offset = self.position.row;
} else if self.position.row >= current_row_offset + viewport_height {
new_row_offset = self.position.row.saturating_sub(viewport_height / 2);
}
if self.position.column < current_col_offset {
new_col_offset = self.position.column;
} else if self.position.column >= current_col_offset + viewport_width {
new_col_offset = self.position.column.saturating_sub(viewport_width / 2);
}
(new_row_offset, new_col_offset)
}
}