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    AppState,
7    colors::{TEXT_NORMAL, border_color},
8    components::{Component, ComponentRender, RenderProps},
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 = Style::default().fg(border_color(props.is_focused).into());
48
49        let block = Block::bordered().border_style(border_style);
50        let area = block.inner(props.area);
51        frame.render_widget(block, props.area);
52
53        RenderProps { area, ..props }
54    }
55
56    fn render_content(&self, frame: &mut ratatui::Frame, props: RenderProps) {
57        let text = "No active view";
58
59        frame.render_widget(
60            Line::from(text)
61                .style(Style::default().fg(TEXT_NORMAL.into()))
62                .alignment(Alignment::Center),
63            props.area,
64        );
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::{
72        test_utils::{assert_buffer_eq, setup_test_terminal, state_with_everything},
73        ui::components::content_view::ActiveView,
74    };
75    use ratatui::buffer::Buffer;
76
77    #[test]
78    fn test_render() {
79        let (tx, _) = tokio::sync::mpsc::unbounded_channel();
80        let view = NoneView::new(&AppState::default(), tx).move_with_state(&AppState {
81            active_view: ActiveView::None,
82            ..state_with_everything()
83        });
84
85        let (mut terminal, area) = setup_test_terminal(16, 3);
86        let props = RenderProps {
87            area,
88            is_focused: true,
89        };
90        let buffer = terminal
91            .draw(|frame| view.render(frame, props))
92            .unwrap()
93            .buffer
94            .clone();
95        #[rustfmt::skip]
96        let expected = Buffer::with_lines([
97            "┌──────────────┐",
98            "│No active view│",
99            "└──────────────┘",
100        ]);
101
102        assert_buffer_eq(&buffer, &expected);
103    }
104}