1use derive_getters::Getters;
2use ratatui::prelude::Rect;
3
4#[cfg(feature = "crossterm")]
5use ratatui::crossterm::event::{MouseButton, MouseEvent, MouseEventKind};
6
7#[derive(Clone, Debug, Default, Getters)]
8pub struct PopupState {
9 pub(crate) area: Option<Rect>,
11 pub(crate) drag_state: DragState,
13}
14
15#[derive(Clone, Debug, Default)]
16pub enum DragState {
17 #[default]
18 NotDragging,
19 Dragging {
20 col_offset: u16,
21 row_offset: u16,
22 },
23}
24
25impl PopupState {
26 pub fn move_by(&mut self, x: i32, y: i32) {
28 if let Some(area) = self.area {
29 self.area.replace(Rect {
30 x: i32::from(area.x)
31 .saturating_add(x)
32 .try_into()
33 .unwrap_or(area.x),
34 y: i32::from(area.y)
35 .saturating_add(y)
36 .try_into()
37 .unwrap_or(area.y),
38 ..area
39 });
40 }
41 }
42
43 pub fn move_to(&mut self, x: u16, y: u16) {
45 if let Some(area) = self.area {
46 self.area.replace(Rect { x, y, ..area });
47 }
48 }
49
50 pub fn mouse_down(&mut self, col: u16, row: u16) {
52 if let Some(area) = self.area {
53 if area.contains((col, row).into()) {
54 self.drag_state = DragState::Dragging {
55 col_offset: col.saturating_sub(area.x),
56 row_offset: row.saturating_sub(area.y),
57 };
58 }
59 }
60 }
61
62 pub fn mouse_up(&mut self, _col: u16, _row: u16) {
64 self.drag_state = DragState::NotDragging;
65 }
66
67 pub fn mouse_drag(&mut self, col: u16, row: u16) {
69 if let DragState::Dragging {
70 col_offset,
71 row_offset,
72 } = self.drag_state
73 {
74 if let Some(area) = self.area {
75 let x = col.saturating_sub(col_offset);
76 let y = row.saturating_sub(row_offset);
77 self.area.replace(Rect { x, y, ..area });
78 }
79 }
80 }
81
82 #[cfg(feature = "crossterm")]
83 pub fn handle_mouse_event(&mut self, event: MouseEvent) {
84 match event.kind {
85 MouseEventKind::Down(MouseButton::Left) => self.mouse_down(event.column, event.row),
86 MouseEventKind::Up(MouseButton::Left) => self.mouse_up(event.column, event.row),
87 MouseEventKind::Drag(MouseButton::Left) => self.mouse_drag(event.column, event.row),
88 _ => {}
89 }
90 }
91}