use ratatui::layout::Rect;
use crate::protocol::NodeId;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Selection {
InitialHyp { hyp_idx: usize },
Hyp { node_id: NodeId, hyp_idx: usize },
Goal { node_id: NodeId, goal_idx: usize },
Theorem,
Error { node_id: NodeId, error_idx: usize },
}
#[derive(Debug, Clone, Copy)]
pub struct Region {
pub x: i32,
pub y: i32,
pub width: u16,
pub height: u16,
pub selection: Selection,
}
impl Region {
pub fn from_rect(area: Rect, selection: Selection) -> Self {
Self {
x: i32::from(area.x),
y: i32::from(area.y),
width: area.width,
height: area.height,
selection,
}
}
pub fn contains(&self, x: u16, y: u16) -> bool {
let px = i32::from(x);
let py = i32::from(y);
px >= self.x
&& px < self.x + i32::from(self.width)
&& py >= self.y
&& py < self.y + i32::from(self.height)
}
}
pub fn find_region_at(regions: &[Region], x: u16, y: u16) -> Option<Selection> {
regions
.iter()
.find(|r| r.contains(x, y))
.map(|r| r.selection)
}
#[derive(Debug, Default)]
pub struct ListSelection {
selected_index: Option<usize>,
regions: Vec<Region>,
}
impl ListSelection {
pub fn clear_regions(&mut self) {
self.regions.clear();
}
pub fn add_region(&mut self, area: Rect, selection: Selection) {
self.regions.push(Region::from_rect(area, selection));
}
pub fn reset(&mut self, item_count: usize) {
self.selected_index = (item_count > 0).then_some(0);
}
pub fn select_previous(&mut self, item_count: usize) {
if item_count == 0 {
return;
}
self.selected_index = Some(self.selected_index.map_or(0, |i| i.saturating_sub(1)));
}
pub const fn select_next(&mut self, item_count: usize) {
if item_count == 0 {
return;
}
self.selected_index = Some(match self.selected_index {
Some(i) if i < item_count - 1 => i + 1,
Some(i) => i,
None => 0,
});
}
pub fn current_selection<'a>(&self, items: &'a [Selection]) -> Option<&'a Selection> {
self.selected_index.and_then(|i| items.get(i))
}
pub fn handle_click(&mut self, x: u16, y: u16, items: &[Selection]) -> bool {
let Some(sel) = find_region_at(&self.regions, x, y) else {
return false;
};
if let Some(idx) = items.iter().position(|i| *i == sel) {
self.selected_index = Some(idx);
return true;
}
false
}
}