summaryrefslogtreecommitdiffstats
path: root/src/canvas/widgets/cpu_basic.rs
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2020-03-07 23:47:53 -0500
committerClementTsang <cjhtsang@uwaterloo.ca>2020-03-07 23:47:53 -0500
commit03ec52c5b16d8968e14e1a648bd2ef4b9489380e (patch)
tree2de0ee608bbf72255be03b3fab35f87ab14fd11a /src/canvas/widgets/cpu_basic.rs
parent132a5a2170294f0d5c463ecba77de1aab32183db (diff)
Split up widgets to make it a bit easier to work with.
Diffstat (limited to 'src/canvas/widgets/cpu_basic.rs')
-rw-r--r--src/canvas/widgets/cpu_basic.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/canvas/widgets/cpu_basic.rs b/src/canvas/widgets/cpu_basic.rs
new file mode 100644
index 00000000..464d8423
--- /dev/null
+++ b/src/canvas/widgets/cpu_basic.rs
@@ -0,0 +1,129 @@
+use std::cmp::{max, min};
+
+use crate::{
+ app::{App, WidgetPosition},
+ canvas::{drawing_utils::*, Painter},
+ constants::*,
+ data_conversion::ConvertedCpuData,
+};
+
+use tui::{
+ backend::Backend,
+ layout::{Constraint, Direction, Layout, Rect},
+ terminal::Frame,
+ widgets::{Block, Paragraph, Text, Widget},
+};
+
+pub trait CpuBasicWidget {
+ fn draw_basic_cpu<B: Backend>(&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect);
+}
+
+impl CpuBasicWidget for Painter {
+ fn draw_basic_cpu<B: Backend>(
+ &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect,
+ ) {
+ let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data;
+
+ // This is a bit complicated, but basically, we want to draw SOME number
+ // of columns to draw all CPUs. Ideally, as well, we want to not have
+ // to ever scroll.
+ // **General logic** - count number of elements in cpu_data. Then see how
+ // many rows and columns we have in draw_loc (-2 on both sides for border?).
+ // I think what we can do is try to fit in as many in one column as possible.
+ // If not, then add a new column.
+ // Then, from this, split the row space across ALL columns. From there, generate
+ // the desired lengths.
+
+ if let WidgetPosition::BasicCpu = app_state.current_widget_selected {
+ Block::default()
+ .borders(*SIDE_BORDERS)
+ .border_style(self.colours.highlighted_border_style)
+ .render(f, draw_loc);
+ }
+
+ let num_cpus = cpu_data.len();
+ if draw_loc.height > 0 {
+ let remaining_height = draw_loc.height as usize;
+ const REQUIRED_COLUMNS: usize = 4;
+
+ let chunk_vec =
+ vec![Constraint::Percentage((100 / REQUIRED_COLUMNS) as u16); REQUIRED_COLUMNS];
+ let chunks = Layout::default()
+ .constraints(chunk_vec.as_ref())
+ .direction(Direction::Horizontal)
+ .split(draw_loc);
+
+ // +9 due to 3 + 4 + 2 columns for the name & space + percentage + bar bounds
+ let margin_space = 2;
+ let remaining_width = max(
+ 0,
+ draw_loc.width as i64
+ - ((9 + margin_space) * REQUIRED_COLUMNS - margin_space) as i64,
+ ) as usize;
+
+ let bar_length = remaining_width / REQUIRED_COLUMNS;
+
+ // CPU (and RAM) percent bars are, uh, "heavily" inspired from htop.
+ let cpu_bars = (0..num_cpus)
+ .map(|cpu_index| {
+ let use_percentage =
+ if let Some(cpu_usage) = cpu_data[cpu_index].cpu_data.last() {
+ cpu_usage.1
+ } else {
+ 0.0
+ };
+
+ let num_bars = calculate_basic_use_bars(use_percentage, bar_length);
+ format!(
+ "{:3}[{}{}{:3.0}%]\n",
+ if app_state.app_config_fields.show_average_cpu {
+ if cpu_index == 0 {
+ "AVG".to_string()
+ } else {
+ (cpu_index - 1).to_string()
+ }
+ } else {
+ cpu_index.to_string()
+ },
+ "|".repeat(num_bars),
+ " ".repeat(bar_length - num_bars),
+ use_percentage.round(),
+ )
+ })
+ .collect::<Vec<_>>();
+
+ let mut row_counter = num_cpus;
+ let mut start_index = 0;
+ for (itx, chunk) in chunks.iter().enumerate() {
+ let to_divide = REQUIRED_COLUMNS - itx;
+ let how_many_cpus = min(
+ remaining_height,
+ (row_counter / to_divide) + (if row_counter % to_divide == 0 { 0 } else { 1 }),
+ );
+ row_counter -= how_many_cpus;
+ let end_index = min(start_index + how_many_cpus, num_cpus);
+ let cpu_column: Vec<Text<'_>> = (start_index..end_index)
+ .map(|cpu_index| {
+ Text::Styled(
+ (&cpu_bars[cpu_index]).into(),
+ self.colours.cpu_colour_styles
+ [cpu_index as usize % self.colours.cpu_colour_styles.len()],
+ )
+ })
+ .collect::<Vec<_>>();
+
+ start_index += how_many_cpus;
+
+ let margined_loc = Layout::default()
+ .direction(Direction::Horizontal)
+ .constraints([Constraint::Percentage(100)].as_ref())
+ .horizontal_margin(1)
+ .split(*chunk);
+
+ Paragraph::new(cpu_column.iter())
+ .block(Block::default())
+ .render(f, margined_loc[0]);
+ }
+ }
+ }
+}