summaryrefslogtreecommitdiffstats
path: root/src/app/widgets/bottom_widgets/mem.rs
blob: 1531290b7a1f0c6492d594cd874a49be32899bcd (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
use std::{borrow::Cow, collections::HashMap, time::Instant};

use crossterm::event::{KeyEvent, MouseEvent};
use tui::{backend::Backend, layout::Rect};

use crate::{
    app::{event::WidgetEventResult, time_graph::TimeGraphData, DataCollection},
    app::{Component, TimeGraph, Widget},
    data_conversion::{convert_mem_data_points, convert_mem_labels, convert_swap_data_points},
    options::layout_options::LayoutRule,
};

pub struct MemWidgetState {
    pub current_display_time: u64,
    pub autohide_timer: Option<Instant>,
}

#[derive(Default)]
pub struct MemState {
    pub force_update: Option<u64>,
    pub widget_states: HashMap<u64, MemWidgetState>,
}

/// A widget that deals with displaying memory usage on a [`TimeGraph`].  Basically just a wrapper
/// around [`TimeGraph`] as of now.
pub struct MemGraph {
    graph: TimeGraph,
    mem_labels: Option<(String, String)>,
    swap_labels: Option<(String, String)>,
    mem_data: Vec<(f64, f64)>,
    swap_data: Vec<(f64, f64)>,
    bounds: Rect,
    width: LayoutRule,
    height: LayoutRule,
}

impl MemGraph {
    /// Creates a new [`MemGraph`].
    pub fn new(graph: TimeGraph) -> Self {
        Self {
            graph,
            mem_labels: Default::default(),
            swap_labels: Default::default(),
            mem_data: Default::default(),
            swap_data: Default::default(),
            bounds: Rect::default(),
            width: LayoutRule::default(),
            height: LayoutRule::default(),
        }
    }

    /// Sets the width.
    pub fn width(mut self, width: LayoutRule) -> Self {
        self.width = width;
        self
    }

    /// Sets the height.
    pub fn height(mut self, height: LayoutRule) -> Self {
        self.height = height;
        self
    }
}

impl Component for MemGraph {
    fn handle_key_event(&mut self, event: KeyEvent) -> WidgetEventResult {
        self.graph.handle_key_event(event)
    }

    fn handle_mouse_event(&mut self, event: MouseEvent) -> WidgetEventResult {
        self.graph.handle_mouse_event(event)
    }

    fn bounds(&self) -> Rect {
        self.bounds
    }

    fn set_bounds(&mut self, new_bounds: Rect) {
        self.bounds = new_bounds;
    }
}

impl Widget for MemGraph {
    fn get_pretty_name(&self) -> &'static str {
        "Memory"
    }

    fn draw<B: Backend>(
        &mut self, painter: &crate::canvas::Painter, f: &mut tui::Frame<'_, B>, area: Rect,
        selected: bool, expanded: bool,
    ) {
        let block = self
            .block()
            .selected(selected)
            .expanded(expanded)
            .build(painter, area);

        let mut chart_data = Vec::with_capacity(2);
        if let Some((label_percent, label_frac)) = &self.mem_labels {
            let mem_label = format!("RAM:{}{}", label_percent, label_frac);
            chart_data.push(TimeGraphData {
                data: &self.mem_data,
                label: Some(mem_label.into()),
                style: painter.colours.ram_style,
            });
        }
        if let Some((label_percent, label_frac)) = &self.swap_labels {
            let swap_label = format!("SWP:{}{}", label_percent, label_frac);
            chart_data.push(TimeGraphData {
                data: &self.swap_data,
                label: Some(swap_label.into()),
                style: painter.colours.swap_style,
            });
        }

        const Y_BOUNDS: [f64; 2] = [0.0, 100.5];
        let y_bound_labels: [Cow<'static, str>; 2] = ["0%".into(), "100%".into()];

        self.graph.draw_tui_chart(
            painter,
            f,
            &chart_data,
            &y_bound_labels,
            Y_BOUNDS,
            false,
            block,
            area,
        );
    }

    fn update_data(&mut self, data_collection: &DataCollection) {
        self.mem_data = convert_mem_data_points(data_collection, false); // TODO: I think the "is_frozen" part is useless... it's always false now.
        self.swap_data = convert_swap_data_points(data_collection, false);
        let (memory_labels, swap_labels) = convert_mem_labels(data_collection);

        self.mem_labels = memory_labels;
        self.swap_labels = swap_labels;
    }

    fn width(&self) -> LayoutRule {
        self.width
    }

    fn height(&self) -> LayoutRule {
        self.height
    }
}