summaryrefslogtreecommitdiffstats
path: root/src/canvas/widgets/disk_table.rs
blob: 2e4dbd2a84459a7a9ed157ad8440dc07627c9089 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use lazy_static::lazy_static;
use std::cmp::max;
use tui::{
    backend::Backend,
    layout::{Constraint, Direction, Layout, Rect},
    terminal::Frame,
    widgets::{Block, Borders, Row, Table, Widget},
};

use crate::{
    app::{self, WidgetPosition},
    canvas::{
        drawing_utils::{get_start_position, get_variable_intrinsic_widths},
        Painter,
    },
    constants::*,
};

const DISK_HEADERS: [&str; 7] = ["Disk", "Mount", "Used", "Free", "Total", "R/s", "W/s"];

lazy_static! {
    static ref DISK_HEADERS_LENS: Vec<usize> = DISK_HEADERS
        .iter()
        .map(|entry| max(FORCE_MIN_THRESHOLD, entry.len()))
        .collect::<Vec<_>>();
}

pub trait DiskTableWidget {
    fn draw_disk_table<B: Backend>(
        &self, f: &mut Frame<'_, B>, app_state: &mut app::App, draw_loc: Rect, draw_border: bool,
    );
}

impl DiskTableWidget for Painter {
    fn draw_disk_table<B: Backend>(
        &self, f: &mut Frame<'_, B>, app_state: &mut app::App, draw_loc: Rect, draw_border: bool,
    ) {
        let disk_data: &[Vec<String>] = &app_state.canvas_data.disk_data;
        let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
        let start_position = get_start_position(
            num_rows,
            &app_state.app_scroll_positions.scroll_direction,
            &mut app_state
                .app_scroll_positions
                .disk_scroll_state
                .previous_scroll_position,
            app_state
                .app_scroll_positions
                .disk_scroll_state
                .current_scroll_position,
            app_state.is_resized,
        );

        let sliced_vec = &disk_data[start_position as usize..];
        let mut disk_counter: i64 = 0;

        let disk_rows = sliced_vec.iter().map(|disk| {
            Row::StyledData(
                disk.iter(),
                match app_state.current_widget_selected {
                    WidgetPosition::Disk => {
                        if disk_counter as u64
                            == app_state
                                .app_scroll_positions
                                .disk_scroll_state
                                .current_scroll_position
                                - start_position
                        {
                            disk_counter = -1;
                            self.colours.currently_selected_text_style
                        } else {
                            if disk_counter >= 0 {
                                disk_counter += 1;
                            }
                            self.colours.text_style
                        }
                    }
                    _ => self.colours.text_style,
                },
            )
        });

        // Calculate widths
        // TODO: [PRETTY] Ellipsis on strings?
        let width = f64::from(draw_loc.width);
        let width_ratios = [0.2, 0.15, 0.13, 0.13, 0.13, 0.13, 0.13];
        let variable_intrinsic_results =
            get_variable_intrinsic_widths(width as u16, &width_ratios, &DISK_HEADERS_LENS);
        let intrinsic_widths = &variable_intrinsic_results.0[0..variable_intrinsic_results.1];

        let title = if app_state.is_expanded {
            const TITLE_BASE: &str = " Disk ── Esc to go back ";
            let repeat_num = max(
                0,
                draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2,
            );
            let result_title = format!(
                " Disk ─{}─ Esc to go back ",
                "─".repeat(repeat_num as usize)
            );
            result_title
        } else if app_state.app_config_fields.use_basic_mode {
            String::new()
        } else {
            " Disk ".to_string()
        };

        let disk_block = if draw_border {
            Block::default()
                .title(&title)
                .title_style(if app_state.is_expanded {
                    match app_state.current_widget_selected {
                        WidgetPosition::Disk => self.colours.highlighted_border_style,
                        _ => self.colours.border_style,
                    }
                } else {
                    self.colours.widget_title_style
                })
                .borders(Borders::ALL)
                .border_style(match app_state.current_widget_selected {
                    WidgetPosition::Disk => self.colours.highlighted_border_style,
                    _ => self.colours.border_style,
                })
        } else {
            match app_state.current_widget_selected {
                WidgetPosition::Disk => Block::default()
                    .borders(*SIDE_BORDERS)
                    .border_style(self.colours.highlighted_border_style),
                _ => Block::default().borders(Borders::NONE),
            }
        };

        let margined_draw_loc = Layout::default()
            .constraints([Constraint::Percentage(100)].as_ref())
            .horizontal_margin(match app_state.current_widget_selected {
                WidgetPosition::Disk => 0,
                _ if !draw_border => 1,
                _ => 0,
            })
            .direction(Direction::Horizontal)
            .split(draw_loc);

        // Draw!
        Table::new(DISK_HEADERS.iter(), disk_rows)
            .block(disk_block)
            .header_style(self.colours.table_header_style)
            .widths(
                &(intrinsic_widths
                    .iter()
                    .map(|calculated_width| Constraint::Length(*calculated_width as u16))
                    .collect::<Vec<_>>()),
            )
            .render(f, margined_draw_loc[0]);
    }
}