rust_kanban/ui/widgets/
mod.rs

1use crate::{app::App, ui::theme::Theme};
2use close_button::CloseButtonWidget;
3use command_palette::CommandPaletteWidget;
4use date_time_picker::{CalenderType, DateTimePickerWidget};
5use ratatui::layout::Rect;
6use std::sync::Arc;
7use tag_picker::TagPickerWidget;
8use toast::ToastWidget;
9
10pub mod close_button;
11pub mod command_palette;
12pub mod date_time_picker;
13pub mod tag_picker;
14pub mod toast;
15
16trait Widget {
17    fn update(app: &mut App);
18}
19
20pub struct WidgetManager<'a> {
21    pub app: Arc<tokio::sync::Mutex<App<'a>>>,
22}
23
24impl WidgetManager<'_> {
25    pub fn new(app: Arc<tokio::sync::Mutex<App>>) -> WidgetManager {
26        WidgetManager { app }
27    }
28
29    pub async fn update(&mut self) {
30        let mut app = self.app.lock().await;
31        ToastWidget::update(&mut app);
32        CommandPaletteWidget::update(&mut app);
33        CloseButtonWidget::update(&mut app);
34        DateTimePickerWidget::update(&mut app);
35        TagPickerWidget::update(&mut app);
36    }
37}
38
39pub struct Widgets<'a> {
40    pub command_palette: CommandPaletteWidget,
41    pub close_button: CloseButtonWidget,
42    pub toast_widget: ToastWidget,
43    pub date_time_picker: DateTimePickerWidget<'a>,
44    pub tag_picker: TagPickerWidget,
45}
46
47impl<'a> Widgets<'a> {
48    pub fn new(theme: Theme, debug_mode: bool, calender_type: CalenderType) -> Self {
49        Self {
50            command_palette: CommandPaletteWidget::new(debug_mode),
51            close_button: CloseButtonWidget::new(theme.general_style),
52            toast_widget: ToastWidget::default(),
53            date_time_picker: DateTimePickerWidget::new(calender_type),
54            tag_picker: TagPickerWidget::default(),
55        }
56    }
57}
58
59#[derive(Debug)]
60enum WidgetAnimState {
61    Closed,
62    Closing,
63    Open,
64    Opening,
65}
66
67impl WidgetAnimState {
68    fn complete_current_stage(&self) -> Self {
69        match self {
70            Self::Closed => Self::Closed,
71            Self::Closing => Self::Closed,
72            Self::Open => Self::Open,
73            Self::Opening => Self::Open,
74        }
75    }
76}
77
78pub trait SelfViewportCorrection {
79    fn get_anchor(&self) -> Option<(u16, u16)>;
80    fn get_last_anchor(&self) -> Option<(u16, u16)>;
81    fn get_viewport_corrected_anchor(&self) -> Option<(u16, u16)>;
82    fn get_last_corrected_viewport(&self) -> Option<Rect>;
83    fn get_current_viewport(&self) -> Option<Rect>;
84    fn set_anchor(&mut self, anchor: Option<(u16, u16)>);
85    fn set_last_anchor(&mut self, anchor: Option<(u16, u16)>);
86    fn set_viewport_corrected_anchor(&mut self, anchor: Option<(u16, u16)>);
87    fn set_last_corrected_viewport(&mut self, anchor: Option<Rect>);
88    fn set_current_viewport(&mut self, anchor: Option<Rect>);
89    fn self_correct(&mut self, target_height: u16, target_width: u16) {
90        if self.get_current_viewport().is_some()
91            && self.get_anchor().is_some()
92            && (self.get_last_corrected_viewport() != self.get_current_viewport()
93                || self.get_last_anchor() != self.get_anchor())
94        {
95            if let (Some(anchor), Some(viewport)) = (self.get_anchor(), self.get_current_viewport())
96            {
97                let mut viewport_corrected_anchor = anchor;
98                if anchor.1 + target_height > viewport.height {
99                    viewport_corrected_anchor.1 = viewport_corrected_anchor
100                        .1
101                        .saturating_sub((anchor.1 + target_height).saturating_sub(viewport.height));
102                }
103                if anchor.0 + target_width > viewport.width {
104                    viewport_corrected_anchor.0 = viewport_corrected_anchor
105                        .0
106                        .saturating_sub((anchor.0 + target_width).saturating_sub(viewport.width));
107                }
108                self.set_viewport_corrected_anchor(Some(viewport_corrected_anchor));
109                self.set_last_corrected_viewport(Some(viewport));
110            }
111        }
112    }
113}