rat_widget/calendar/
no_selection.rs

1use crate::calendar::event::CalOutcome;
2use crate::calendar::{CalendarSelection, CalendarState, MonthState};
3use chrono::NaiveDate;
4use rat_event::{ConsumedEvent, HandleEvent, MouseOnly, Regular, ct_event};
5use rat_focus::HasFocus;
6use ratatui_crossterm::crossterm::event::Event;
7
8/// No selection model
9///
10/// Can scroll the calendar with Up/Down, PageUp/PageDown though.
11/// Ctrl+Home moves to today.
12///
13#[derive(Debug, Default, Clone)]
14pub struct NoSelection;
15
16impl CalendarSelection for NoSelection {
17    fn count(&self) -> usize {
18        0
19    }
20
21    fn is_selected(&self, _: NaiveDate) -> bool {
22        false
23    }
24
25    fn lead_selection(&self) -> Option<NaiveDate> {
26        None
27    }
28}
29
30impl HandleEvent<Event, Regular, CalOutcome> for MonthState<NoSelection> {
31    fn handle(&mut self, event: &Event, _qualifier: Regular) -> CalOutcome {
32        self.handle(event, MouseOnly)
33    }
34}
35
36impl HandleEvent<Event, MouseOnly, CalOutcome> for MonthState<NoSelection> {
37    fn handle(&mut self, _event: &Event, _qualifier: MouseOnly) -> CalOutcome {
38        CalOutcome::Continue
39    }
40}
41
42impl<const N: usize> HandleEvent<Event, Regular, CalOutcome> for CalendarState<N, NoSelection> {
43    fn handle(&mut self, event: &Event, _qualifier: Regular) -> CalOutcome {
44        let mut r = 'f: {
45            for month in &mut self.months {
46                let r = month.handle(event, Regular);
47                if r == CalOutcome::Selected {
48                    self.focus_lead();
49                    break 'f r;
50                }
51            }
52            CalOutcome::Continue
53        };
54
55        r = r.or_else(|| {
56            if self.is_focused() {
57                match event {
58                    ct_event!(keycode press CONTROL-Home) => self.move_to_today(),
59                    ct_event!(keycode press PageUp) => self.prev_month(1),
60                    ct_event!(keycode press PageDown) => self.next_month(1),
61                    ct_event!(keycode press Up) => self.prev_month(1),
62                    ct_event!(keycode press Down) => self.next_month(1),
63                    _ => CalOutcome::Continue,
64                }
65            } else {
66                CalOutcome::Continue
67            }
68        });
69
70        r.or_else(|| self.handle(event, MouseOnly))
71    }
72}
73
74impl<const N: usize> HandleEvent<Event, MouseOnly, CalOutcome> for CalendarState<N, NoSelection> {
75    fn handle(&mut self, event: &Event, _qualifier: MouseOnly) -> CalOutcome {
76        for i in 0..self.months.len() {
77            if self.months[i].gained_focus() {
78                self.set_primary_idx(i);
79                break;
80            }
81        }
82
83        let all_areas = self
84            .months
85            .iter()
86            .map(|v| v.area)
87            .reduce(|v, w| v.union(w))
88            .unwrap_or_default();
89        match event {
90            ct_event!(scroll up for x,y) if all_areas.contains((*x, *y).into()) => {
91                self.scroll_back(self.step())
92            }
93            ct_event!(scroll down for x,y) if all_areas.contains((*x, *y).into()) => {
94                self.scroll_forward(self.step())
95            }
96            _ => CalOutcome::Continue,
97        }
98    }
99}