use crossterm::event::{MouseButton, MouseEvent, MouseEventKind};
use crate::app::Panel;
use crate::layout::AppLayout;
use super::App;
use super::action::{Action, ScrollDir};
use super::reducer::{reduce, run_effects};
impl App {
pub(crate) fn handle_mouse(&mut self, event: MouseEvent) {
let Some(layout) = self.last_layout else {
return;
};
let Some(action) = decode_mouse(event, &layout) else {
return;
};
let effects = reduce(self, action);
run_effects(self, effects);
}
}
fn decode_mouse(event: MouseEvent, layout: &AppLayout) -> Option<Action> {
match event.kind {
MouseEventKind::ScrollUp => Some(Action::ScrollLines(-3)),
MouseEventKind::ScrollDown => Some(Action::ScrollLines(3)),
MouseEventKind::Down(MouseButton::Left) => {
let col = event.column;
let row = event.row;
if rect_contains(layout.skills, col, row) {
return Some(Action::SetActivePanel(Panel::Skills));
}
if rect_contains(layout.memory, col, row) {
return Some(Action::SetActivePanel(Panel::Memory));
}
if rect_contains(layout.resources, col, row) {
return Some(Action::SetActivePanel(Panel::Resources));
}
if rect_contains(layout.subagents, col, row) {
return Some(Action::SetActivePanel(Panel::SubAgents));
}
if rect_contains(layout.chat, col, row) {
return Some(Action::SetActivePanel(Panel::Chat));
}
if rect_contains(layout.input, col, row) {
return Some(Action::EnterInsert);
}
None
}
MouseEventKind::Down(MouseButton::Right) => {
if rect_contains(layout.chat, event.column, event.row) {
Some(Action::ScrollPage(ScrollDir::Up))
} else {
None
}
}
_ => None,
}
}
fn rect_contains(rect: ratatui::layout::Rect, col: u16, row: u16) -> bool {
col >= rect.x
&& col < rect.x.saturating_add(rect.width)
&& row >= rect.y
&& row < rect.y.saturating_add(rect.height)
}