diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2020-08-28 16:30:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-28 16:30:24 -0400 |
commit | 9a11e77aa057bb4b9d3d31d3c70ceab7136eedaf (patch) | |
tree | 64d32c8bd0e4ed43c9af3f34137d905e5fe0f99f /src/canvas/widgets | |
parent | 81ec7c311b5cf915032c473b411c8a1d0bb13228 (diff) |
feature: Adaptive network widget (#206)
Allows the network widget graph to grow/shrink with current data, rather than using a static size.
Diffstat (limited to 'src/canvas/widgets')
-rw-r--r-- | src/canvas/widgets/cpu_graph.rs | 3 | ||||
-rw-r--r-- | src/canvas/widgets/mem_graph.rs | 3 | ||||
-rw-r--r-- | src/canvas/widgets/network_graph.rs | 105 |
3 files changed, 104 insertions, 7 deletions
diff --git a/src/canvas/widgets/cpu_graph.rs b/src/canvas/widgets/cpu_graph.rs index f31eb1f2..bd931deb 100644 --- a/src/canvas/widgets/cpu_graph.rs +++ b/src/canvas/widgets/cpu_graph.rs @@ -144,10 +144,9 @@ impl CpuGraphWidget for Painter { .labels_style(self.colours.graph_style) }; - // Note this is offset as otherwise the 0 value is not drawn! let y_axis = Axis::default() .style(self.colours.graph_style) - .bounds([-0.5, 100.5]) + .bounds([0.0, 100.5]) .labels_style(self.colours.graph_style) .labels(&["0%", "100%"]); diff --git a/src/canvas/widgets/mem_graph.rs b/src/canvas/widgets/mem_graph.rs index 1097c493..b6cb1af1 100644 --- a/src/canvas/widgets/mem_graph.rs +++ b/src/canvas/widgets/mem_graph.rs @@ -54,10 +54,9 @@ impl MemGraphWidget for Painter { .labels_style(self.colours.graph_style) }; - // Offset as the zero value isn't drawn otherwise... let y_axis = Axis::default() .style(self.colours.graph_style) - .bounds([-0.5, 100.5]) + .bounds([0.0, 100.5]) .labels(&["0%", "100%"]) .labels_style(self.colours.graph_style); diff --git a/src/canvas/widgets/network_graph.rs b/src/canvas/widgets/network_graph.rs index b981c15f..d69f68f3 100644 --- a/src/canvas/widgets/network_graph.rs +++ b/src/canvas/widgets/network_graph.rs @@ -5,6 +5,7 @@ use crate::{ app::App, canvas::{drawing_utils::get_variable_intrinsic_widths, Painter}, constants::*, + utils::gen_util::*, }; use tui::{ @@ -67,10 +68,109 @@ impl NetworkGraphWidget for Painter { &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64, hide_legend: bool, ) { + /// Point is of time, data + type Point = (f64, f64); + + /// Returns the required max data point and labels. + fn adjust_network_data_point( + rx: &[Point], tx: &[Point], time_start: f64, time_end: f64, + ) -> (f64, Vec<String>) { + // First, filter and find the maximal rx or tx so we know how to scale + let mut max_val_bytes = 0.0; + let filtered_rx = rx + .iter() + .cloned() + .filter(|(time, _data)| *time >= time_start && *time <= time_end); + + let filtered_tx = tx + .iter() + .cloned() + .filter(|(time, _data)| *time >= time_start && *time <= time_end); + + for (_time, data) in filtered_rx.clone().chain(filtered_tx.clone()) { + if data > max_val_bytes { + max_val_bytes = data; + } + } + + // Main idea is that we have some "limits" --- if we're, say, under a logged kibibyte, + // then we are just gonna set the cap at a kibibyte. + // For gibi/giga and beyond, we instead start going up by 1 rather than jumping to a tera/tebi. + // So, it would look a bit like: + // - < Kibi => Kibi => Mebi => Gibi => 2 Gibi => ... => 999 Gibi => Tebi => 2 Tebi => ... + + let true_max_val: f64; + let mut labels = vec![]; + if max_val_bytes < LOG_KIBI_LIMIT { + true_max_val = LOG_KIBI_LIMIT; + labels = vec!["0B".to_string(), "1KiB".to_string()]; + } else if max_val_bytes < LOG_MEBI_LIMIT { + true_max_val = LOG_MEBI_LIMIT; + labels = vec!["0B".to_string(), "1KiB".to_string(), "1MiB".to_string()]; + } else if max_val_bytes < LOG_GIBI_LIMIT { + true_max_val = LOG_GIBI_LIMIT; + labels = vec![ + "0B".to_string(), + "1KiB".to_string(), + "1MiB".to_string(), + "1GiB".to_string(), + ]; + } else if max_val_bytes < LOG_TEBI_LIMIT { + true_max_val = max_val_bytes.ceil() + 1.0; + let cap_u32 = true_max_val as u32; + + for i in 0..=cap_u32 { + match i { + 0 => labels.push("0B".to_string()), + LOG_KIBI_LIMIT_U32 => labels.push("1KiB".to_string()), + LOG_MEBI_LIMIT_U32 => labels.push("1MiB".to_string()), + LOG_GIBI_LIMIT_U32 => labels.push("1GiB".to_string()), + _ if i == cap_u32 => { + labels.push(format!("{}GiB", 2_u64.pow(cap_u32 - LOG_GIBI_LIMIT_U32))) + } + _ if i == (LOG_GIBI_LIMIT_U32 + cap_u32) / 2 => labels.push(format!( + "{}GiB", + 2_u64.pow(cap_u32 - ((LOG_GIBI_LIMIT_U32 + cap_u32) / 2)) + )), // ~Halfway point + _ => labels.push(String::default()), + } + } + } else { + true_max_val = max_val_bytes.ceil() + 1.0; + let cap_u32 = true_max_val as u32; + + for i in 0..=cap_u32 { + match i { + 0 => labels.push("0B".to_string()), + LOG_KIBI_LIMIT_U32 => labels.push("1KiB".to_string()), + LOG_MEBI_LIMIT_U32 => labels.push("1MiB".to_string()), + LOG_GIBI_LIMIT_U32 => labels.push("1GiB".to_string()), + LOG_TEBI_LIMIT_U32 => labels.push("1TiB".to_string()), + _ if i == cap_u32 => { + labels.push(format!("{}GiB", 2_u64.pow(cap_u32 - LOG_TEBI_LIMIT_U32))) + } + _ if i == (LOG_TEBI_LIMIT_U32 + cap_u32) / 2 => labels.push(format!( + "{}TiB", + 2_u64.pow(cap_u32 - ((LOG_TEBI_LIMIT_U32 + cap_u32) / 2)) + )), // ~Halfway point + _ => labels.push(String::default()), + } + } + } + + (true_max_val, labels) + } + if let Some(network_widget_state) = app_state.net_state.widget_states.get_mut(&widget_id) { let network_data_rx: &[(f64, f64)] = &app_state.canvas_data.network_data_rx; let network_data_tx: &[(f64, f64)] = &app_state.canvas_data.network_data_tx; + let (max_range, labels) = adjust_network_data_point( + network_data_rx, + network_data_tx, + -(network_widget_state.current_display_time as f64), + 0.0, + ); let display_time_labels = [ format!("{}s", network_widget_state.current_display_time / 1000), "0s".to_string(), @@ -104,11 +204,10 @@ impl NetworkGraphWidget for Painter { .labels_style(self.colours.graph_style) }; - // 0 is offset. - let y_axis_labels = ["0B", "1KiB", "1MiB", "1GiB"]; + let y_axis_labels = labels; let y_axis = Axis::default() .style(self.colours.graph_style) - .bounds([-0.5, 30_f64]) + .bounds([0.0, max_range]) .labels(&y_axis_labels) .labels_style(self.colours.graph_style); |