Skip to main content

tui/view/
mod.rs

1//! View dispatch types and traits.
2
3pub mod config;
4pub mod console;
5pub mod list;
6pub mod reports;
7#[cfg(test)]
8mod tests;
9
10use crate::event::Intent;
11use crate::tabs::config::ConfigTab;
12use crate::tabs::list::ListTab;
13use crate::tabs::nms::ConsoleState;
14use crate::tabs::reports::ReportsTab;
15use crate::widgets::EditMode;
16use ratatui::Frame;
17use ratatui::layout::Rect;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ViewId {
21    Accounts = 0,
22    Transactions = 1,
23    Commodities = 2,
24    Reports = 3,
25    Config = 4,
26    Console = 5,
27}
28
29impl 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    pub fn index(self) -> usize {
40        self as usize
41    }
42
43    pub fn label(self) -> &'static str {
44        match self {
45            ViewId::Accounts => "Accounts",
46            ViewId::Transactions => "Transactions",
47            ViewId::Commodities => "Commodities",
48            ViewId::Reports => "Reports",
49            ViewId::Config => "Config",
50            ViewId::Console => "Console",
51        }
52    }
53}
54
55/// `Tab` is an alias so existing `Tab::Accounts`, `Tab::ALL`, etc. keep compiling.
56pub type Tab = ViewId;
57
58pub 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
64pub enum Handled {
65    Consumed(Vec<Cmd>),
66    Ignored,
67}
68
69pub enum Cmd {
70    Status(String),
71    SwitchView(ViewId),
72}
73
74/// Immutable borrow of the active tab, carrying identity on the List arm.
75pub 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.
83pub 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
90impl<'a> ViewRef<'a> {
91    pub fn id(&self) -> ViewId {
92        match self {
93            ViewRef::List(id, _) => *id,
94            ViewRef::Reports(_) => ViewId::Reports,
95            ViewRef::Config(_) => ViewId::Config,
96            ViewRef::Console(_) => ViewId::Console,
97        }
98    }
99
100    pub fn title(&self) -> &'static str {
101        self.id().label()
102    }
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    pub fn draw(&self, frame: &mut Frame, area: Rect, ctx: &DrawCtx) {
107        match self {
108            ViewRef::List(id, tab) => tab.draw(frame, area, id.label()),
109            ViewRef::Reports(tab) => tab.draw(frame, area),
110            ViewRef::Config(tab) => tab.draw(frame, area),
111            ViewRef::Console(tab) => tab.draw(frame, area, ctx),
112        }
113    }
114}
115
116impl<'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    pub fn handle(&mut self, intent: Intent, ctx: &DrawCtx) -> Handled {
140        match self {
141            ViewMut::List(_, tab) => tab.handle(intent, ctx),
142            ViewMut::Reports(tab) => tab.handle(intent, ctx),
143            ViewMut::Config(tab) => tab.handle(intent, ctx),
144            ViewMut::Console(tab) => tab.handle(intent, ctx),
145        }
146    }
147}