1
//! View dispatch types and traits.
2

            
3
pub mod config;
4
pub mod console;
5
pub mod list;
6
pub mod reports;
7
#[cfg(test)]
8
mod tests;
9

            
10
use crate::event::Intent;
11
use crate::tabs::config::ConfigTab;
12
use crate::tabs::list::ListTab;
13
use crate::tabs::nms::ConsoleState;
14
use crate::tabs::reports::ReportsTab;
15
use crate::widgets::EditMode;
16
use ratatui::Frame;
17
use ratatui::layout::Rect;
18

            
19
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20
pub enum ViewId {
21
    Accounts = 0,
22
    Transactions = 1,
23
    Commodities = 2,
24
    Reports = 3,
25
    Config = 4,
26
    Console = 5,
27
}
28

            
29
impl ViewId {
30
    pub const ALL: [ViewId; 6] = [
31
        ViewId::Accounts,
32
        ViewId::Transactions,
33
        ViewId::Commodities,
34
        ViewId::Reports,
35
        ViewId::Config,
36
        ViewId::Console,
37
    ];
38

            
39
49
    pub fn index(self) -> usize {
40
49
        self as usize
41
49
    }
42

            
43
198
    pub fn label(self) -> &'static str {
44
198
        match self {
45
34
            ViewId::Accounts => "Accounts",
46
32
            ViewId::Transactions => "Transactions",
47
32
            ViewId::Commodities => "Commodities",
48
33
            ViewId::Reports => "Reports",
49
33
            ViewId::Config => "Config",
50
34
            ViewId::Console => "Console",
51
        }
52
198
    }
53
}
54

            
55
/// `Tab` is an alias so existing `Tab::Accounts`, `Tab::ALL`, etc. keep compiling.
56
pub type Tab = ViewId;
57

            
58
pub struct DrawCtx {
59
    pub edit_mode: EditMode,
60
    /// True when the view currently holds keyboard focus (e.g. console input active).
61
    pub is_active: bool,
62
}
63

            
64
pub enum Handled {
65
    Consumed(Vec<Cmd>),
66
    Ignored,
67
}
68

            
69
pub enum Cmd {
70
    Status(String),
71
    SwitchView(ViewId),
72
}
73

            
74
/// Immutable borrow of the active tab, carrying identity on the List arm.
75
pub enum ViewRef<'a> {
76
    List(ViewId, &'a ListTab),
77
    Reports(&'a ReportsTab),
78
    Config(&'a ConfigTab),
79
    Console(&'a ConsoleState),
80
}
81

            
82
/// Mutable borrow of the active tab, carrying identity on the List arm.
83
pub enum ViewMut<'a> {
84
    List(ViewId, &'a mut ListTab),
85
    Reports(&'a mut ReportsTab),
86
    Config(&'a mut ConfigTab),
87
    Console(&'a mut ConsoleState),
88
}
89

            
90
impl<'a> ViewRef<'a> {
91
8
    pub fn id(&self) -> ViewId {
92
8
        match self {
93
2
            ViewRef::List(id, _) => *id,
94
2
            ViewRef::Reports(_) => ViewId::Reports,
95
2
            ViewRef::Config(_) => ViewId::Config,
96
2
            ViewRef::Console(_) => ViewId::Console,
97
        }
98
8
    }
99

            
100
4
    pub fn title(&self) -> &'static str {
101
4
        self.id().label()
102
4
    }
103

            
104
    /// Dispatch to the tab's inherent draw. The List arm passes its `ViewId`
105
    /// label directly so the body never needs to know its own identity.
106
31
    pub fn draw(&self, frame: &mut Frame, area: Rect, ctx: &DrawCtx) {
107
31
        match self {
108
1
            ViewRef::List(id, tab) => tab.draw(frame, area, id.label()),
109
22
            ViewRef::Reports(tab) => tab.draw(frame, area),
110
            ViewRef::Config(tab) => tab.draw(frame, area),
111
8
            ViewRef::Console(tab) => tab.draw(frame, area, ctx),
112
        }
113
31
    }
114
}
115

            
116
impl<'a> ViewMut<'a> {
117
    pub fn id(&self) -> ViewId {
118
        match self {
119
            ViewMut::List(id, _) => *id,
120
            ViewMut::Reports(_) => ViewId::Reports,
121
            ViewMut::Config(_) => ViewId::Config,
122
            ViewMut::Console(_) => ViewId::Console,
123
        }
124
    }
125

            
126
    pub fn title(&self) -> &'static str {
127
        self.id().label()
128
    }
129

            
130
    pub fn draw(&self, frame: &mut Frame, area: Rect, ctx: &DrawCtx) {
131
        match self {
132
            ViewMut::List(id, tab) => tab.draw(frame, area, id.label()),
133
            ViewMut::Reports(tab) => tab.draw(frame, area),
134
            ViewMut::Config(tab) => tab.draw(frame, area),
135
            ViewMut::Console(tab) => tab.draw(frame, area, ctx),
136
        }
137
    }
138

            
139
47
    pub fn handle(&mut self, intent: Intent, ctx: &DrawCtx) -> Handled {
140
47
        match self {
141
13
            ViewMut::List(_, tab) => tab.handle(intent, ctx),
142
29
            ViewMut::Reports(tab) => tab.handle(intent, ctx),
143
1
            ViewMut::Config(tab) => tab.handle(intent, ctx),
144
4
            ViewMut::Console(tab) => tab.handle(intent, ctx),
145
        }
146
47
    }
147
}