summaryrefslogtreecommitdiffstats
path: root/src/interactive/widgets/main.rs
blob: 3325d916aaf7601e3b5f306319170afb20c675fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::interactive::{
    widgets::{Entries, EntriesProps, Footer, FooterProps, Header, HelpPane, HelpPaneProps},
    AppState, DisplayOptions, FocussedPane,
};
use dua::traverse::Traversal;
use std::borrow::Borrow;
use tui::style::{Color, Style};
use tui::{
    buffer::Buffer,
    layout::{Constraint, Direction, Layout, Rect},
    style::Modifier,
};
use tui_react::ToplevelComponent;

pub struct MainWindowProps<'a> {
    pub traversal: &'a Traversal,
    pub display: DisplayOptions,
    pub state: &'a AppState,
}

#[derive(Default)]
pub struct MainWindow {
    pub help_pane: Option<HelpPane>,
    pub entries_pane: Entries,
}

impl MainWindow {
    pub fn render<'a>(
        &mut self,
        props: impl Borrow<MainWindowProps<'a>>,
        area: Rect,
        buf: &mut Buffer,
    ) {
        let MainWindowProps {
            traversal:
                Traversal {
                    tree,
                    entries_traversed,
                    total_bytes,
                    ..
                },
            display,
            state,
        } = props.borrow();
        let regions = Layout::default()
            .direction(Direction::Vertical)
            .constraints(
                [
                    Constraint::Length(1),
                    Constraint::Max(256),
                    Constraint::Length(1),
                ]
                .as_ref(),
            )
            .split(area);
        let (header_area, entries_area, footer_area) = (regions[0], regions[1], regions[2]);
        let (entries_area, help_pane) = match self.help_pane {
            Some(ref mut pane) => {
                let regions = Layout::default()
                    .direction(Direction::Horizontal)
                    .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
                    .split(entries_area);
                (regions[0], Some((regions[1], pane)))
            }
            None => (entries_area, None),
        };
        let grey = Style {
            fg: Color::DarkGray,
            bg: Color::Reset,
            modifier: Modifier::empty(),
        };
        let white = Style {
            fg: Color::White,
            ..grey
        };
        let (entries_style, help_style) = match state.focussed {
            FocussedPane::Main => (white, grey),
            FocussedPane::Help => (grey, white),
        };

        Header.render(header_area, buf);
        let props = EntriesProps {
            tree: &tree,
            root: state.root,
            display: *display,
            entries: &state.entries,
            selected: state.selected,
            border_style: entries_style,
            is_focussed: if let FocussedPane::Main = state.focussed {
                true
            } else {
                false
            },
        };
        self.entries_pane.render(props, entries_area, buf);

        if let Some((help_area, pane)) = help_pane {
            let props = HelpPaneProps {
                border_style: help_style,
            };
            pane.render(props, help_area, buf);
        }

        Footer.render(
            FooterProps {
                total_bytes: *total_bytes,
                entries_traversed: *entries_traversed,
                format: display.byte_format,
                message: state.message.clone(),
            },
            footer_area,
            buf,
        );
    }
}