mecomp_tui/ui/components/content_view/views/
none.rs

1//! an empty view
2
3use ratatui::{layout::Alignment, style::Style, text::Line, widgets::Block};
4
5use crate::ui::{
6    colors::{BORDER_FOCUSED, BORDER_UNFOCUSED, TEXT_NORMAL},
7    components::{Component, ComponentRender, RenderProps},
8    AppState,
9};
10
11#[allow(clippy::module_name_repetitions)]
12pub struct NoneView;
13
14impl Component for NoneView {
15    fn new(
16        _state: &AppState,
17        _action_tx: tokio::sync::mpsc::UnboundedSender<crate::state::action::Action>,
18    ) -> Self
19    where
20        Self: Sized,
21    {
22        Self
23    }
24
25    fn move_with_state(self, _state: &AppState) -> Self
26    where
27        Self: Sized,
28    {
29        self
30    }
31
32    fn name(&self) -> &'static str {
33        "None"
34    }
35
36    fn handle_key_event(&mut self, _key: crossterm::event::KeyEvent) {
37        // do nothing
38    }
39
40    fn handle_mouse_event(&mut self, _: crossterm::event::MouseEvent, _: ratatui::layout::Rect) {
41        // do nothing
42    }
43}
44
45impl ComponentRender<RenderProps> for NoneView {
46    fn render_border(&self, frame: &mut ratatui::Frame, props: RenderProps) -> RenderProps {
47        let border_style = if props.is_focused {
48            Style::default().fg(BORDER_FOCUSED.into())
49        } else {
50            Style::default().fg(BORDER_UNFOCUSED.into())
51        };
52
53        let block = Block::bordered().border_style(border_style);
54        let area = block.inner(props.area);
55        frame.render_widget(block, props.area);
56
57        RenderProps { area, ..props }
58    }
59
60    fn render_content(&self, frame: &mut ratatui::Frame, props: RenderProps) {
61        let text = "No active view";
62
63        frame.render_widget(
64            Line::from(text)
65                .style(Style::default().fg(TEXT_NORMAL.into()))
66                .alignment(Alignment::Center),
67            props.area,
68        );
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use crate::{
76        test_utils::{assert_buffer_eq, setup_test_terminal, state_with_everything},
77        ui::components::content_view::ActiveView,
78    };
79    use anyhow::Result;
80    use ratatui::buffer::Buffer;
81
82    #[test]
83    fn test_render() -> Result<()> {
84        let (tx, _) = tokio::sync::mpsc::unbounded_channel();
85        let view = NoneView::new(&AppState::default(), tx).move_with_state(&AppState {
86            active_view: ActiveView::None,
87            ..state_with_everything()
88        });
89
90        let (mut terminal, area) = setup_test_terminal(16, 3);
91        let props = RenderProps {
92            area,
93            is_focused: true,
94        };
95        let buffer = terminal
96            .draw(|frame| view.render(frame, props))
97            .unwrap()
98            .buffer
99            .clone();
100        #[rustfmt::skip]
101        let expected = Buffer::with_lines([
102            "┌──────────────┐",
103            "│No active view│",
104            "└──────────────┘",
105        ]);
106
107        assert_buffer_eq(&buffer, &expected);
108
109        Ok(())
110    }
111}