summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClementTsang <cjhtsang@uwaterloo.ca>2020-02-04 22:44:49 -0500
committerClementTsang <cjhtsang@uwaterloo.ca>2020-02-04 22:44:49 -0500
commite0115624a9027d8db4b69092d7ea94bfea4d96e4 (patch)
tree84fd1c6fdce4aefe4301c8a0c8b96483eb161a0d /src
parent41d56d8a9b90609acc2ebdb44c646340812bcdef (diff)
Refactoring - moved canvas into its own struct... time to do some more fun optimization.
Diffstat (limited to 'src')
-rw-r--r--src/canvas.rs1744
-rw-r--r--src/main.rs23
2 files changed, 892 insertions, 875 deletions
diff --git a/src/canvas.rs b/src/canvas.rs
index 64218253..73f55536 100644
--- a/src/canvas.rs
+++ b/src/canvas.rs
@@ -155,428 +155,598 @@ fn gen_n_colours(num_to_gen: i32) -> Vec<Color> {
colour_vec
}
-#[allow(unused_variables)]
-pub fn draw_data<B: backend::Backend>(
- terminal: &mut Terminal<B>, app_state: &mut app::App,
-) -> error::Result<()> {
- terminal.autoresize()?;
- terminal.draw(|mut f| {
- if app_state.show_help {
- // Only for the help
- let vertical_dialog_chunk = Layout::default()
- .direction(Direction::Vertical)
- .margin(1)
- .constraints(
- [
- Constraint::Percentage(22),
- Constraint::Percentage(60),
- Constraint::Percentage(18),
- ]
- .as_ref(),
- )
- .split(f.size());
-
- let middle_dialog_chunk = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints(
- [
- Constraint::Percentage(20),
- Constraint::Percentage(60),
- Constraint::Percentage(20),
- ]
- .as_ref(),
- )
- .split(vertical_dialog_chunk[1]);
-
- Paragraph::new(HELP_TEXT.iter())
- .block(
- Block::default()
- .title("Help (Press Esc to close)")
- .borders(Borders::ALL),
- )
- .style(Style::default().fg(Color::Gray))
- .alignment(Alignment::Left)
- .wrap(true)
- .render(&mut f, middle_dialog_chunk[1]);
- } else if app_state.show_dd {
- let vertical_dialog_chunk = Layout::default()
- .direction(Direction::Vertical)
- .margin(1)
- .constraints(
- [
- Constraint::Percentage(40),
- Constraint::Percentage(20),
- Constraint::Percentage(40),
- ]
- .as_ref(),
- )
- .split(f.size());
-
- let middle_dialog_chunk = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints(
- [
- Constraint::Percentage(30),
- Constraint::Percentage(40),
- Constraint::Percentage(30),
- ]
- .as_ref(),
- )
- .split(vertical_dialog_chunk[1]);
+#[derive(Default)]
+/// Handles the canvas' state.
+pub struct Painter {}
+
+impl Painter {
+ pub fn draw_data<B: backend::Backend>(
+ &mut self, terminal: &mut Terminal<B>, app_state: &mut app::App,
+ ) -> error::Result<()> {
+ terminal.autoresize()?;
+ terminal.draw(|mut f| {
+ if app_state.show_help {
+ // Only for the help
+ let vertical_dialog_chunk = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(1)
+ .constraints(
+ [
+ Constraint::Percentage(22),
+ Constraint::Percentage(60),
+ Constraint::Percentage(18),
+ ]
+ .as_ref(),
+ )
+ .split(f.size());
- if let Some(dd_err) = app_state.dd_err.clone() {
- let dd_text = [Text::raw(format!(
- "\nFailure to properly kill the process - {}",
- dd_err
- ))];
+ let middle_dialog_chunk = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints(
+ [
+ Constraint::Percentage(20),
+ Constraint::Percentage(60),
+ Constraint::Percentage(20),
+ ]
+ .as_ref(),
+ )
+ .split(vertical_dialog_chunk[1]);
- Paragraph::new(dd_text.iter())
+ Paragraph::new(HELP_TEXT.iter())
.block(
Block::default()
- .title("Kill Process Error (Press Esc to close)")
+ .title("Help (Press Esc to close)")
.borders(Borders::ALL),
)
.style(Style::default().fg(Color::Gray))
- .alignment(Alignment::Center)
+ .alignment(Alignment::Left)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
- } else if let Some(to_kill_processes) = app_state.get_to_delete_processes() {
- if let Some(first_pid) = to_kill_processes.1.first() {
- let dd_text = [
- if app_state.is_grouped() {
- Text::raw(format!(
- "\nAre you sure you want to kill {} process(es) with name {}?",
- to_kill_processes.1.len(), to_kill_processes.0
- ))
- } else {
- Text::raw(format!(
- "\nAre you sure you want to kill process {} with PID {}?",
- to_kill_processes.0, first_pid
- ))
- },
- Text::raw("\n\nPress ENTER to proceed, ESC to exit."),
- Text::raw("\nNote that if bottom is frozen, it must be unfrozen for changes to be shown."),
- ];
+ } else if app_state.show_dd {
+ let vertical_dialog_chunk = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(1)
+ .constraints(
+ [
+ Constraint::Percentage(40),
+ Constraint::Percentage(20),
+ Constraint::Percentage(40),
+ ]
+ .as_ref(),
+ )
+ .split(f.size());
+
+ let middle_dialog_chunk = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints(
+ [
+ Constraint::Percentage(30),
+ Constraint::Percentage(40),
+ Constraint::Percentage(30),
+ ]
+ .as_ref(),
+ )
+ .split(vertical_dialog_chunk[1]);
+
+ if let Some(dd_err) = app_state.dd_err.clone() {
+ let dd_text = [Text::raw(format!(
+ "\nFailure to properly kill the process - {}",
+ dd_err
+ ))];
Paragraph::new(dd_text.iter())
.block(
Block::default()
- .title("Kill Process Confirmation (Press Esc to close)")
+ .title("Kill Process Error (Press Esc to close)")
.borders(Borders::ALL),
)
.style(Style::default().fg(Color::Gray))
.alignment(Alignment::Center)
.wrap(true)
.render(&mut f, middle_dialog_chunk[1]);
+ } else if let Some(to_kill_processes) = app_state.get_to_delete_processes() {
+ if let Some(first_pid) = to_kill_processes.1.first() {
+ let dd_text = [
+ if app_state.is_grouped() {
+ Text::raw(format!(
+ "\nAre you sure you want to kill {} process(es) with name {}?",
+ to_kill_processes.1.len(), to_kill_processes.0
+ ))
+ } else {
+ Text::raw(format!(
+ "\nAre you sure you want to kill process {} with PID {}?",
+ to_kill_processes.0, first_pid
+ ))
+ },
+ Text::raw("\n\nPress ENTER to proceed, ESC to exit."),
+ Text::raw("\nNote that if bottom is frozen, it must be unfrozen for changes to be shown."),
+ ];
+
+ Paragraph::new(dd_text.iter())
+ .block(
+ Block::default()
+ .title("Kill Process Confirmation (Press Esc to close)")
+ .borders(Borders::ALL),
+ )
+ .style(Style::default().fg(Color::Gray))
+ .alignment(Alignment::Center)
+ .wrap(true)
+ .render(&mut f, middle_dialog_chunk[1]);
+ } else {
+ // This is a bit nasty, but it works well... I guess.
+ app_state.show_dd = false;
+ }
} else {
// This is a bit nasty, but it works well... I guess.
app_state.show_dd = false;
}
} else {
- // This is a bit nasty, but it works well... I guess.
- app_state.show_dd = false;
- }
- } else {
- let vertical_chunks = Layout::default()
- .direction(Direction::Vertical)
- .margin(1)
- .constraints(
- [
- Constraint::Percentage(30),
- Constraint::Percentage(37),
- Constraint::Percentage(33),
- ]
- .as_ref(),
- )
- .split(f.size());
-
- let middle_chunks = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(60), Constraint::Percentage(40)].as_ref())
- .split(vertical_chunks[1]);
-
- let middle_divided_chunk_2 = Layout::default()
- .direction(Direction::Vertical)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(middle_chunks[1]);
-
- let middle_divide_chunk_3 = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())
- .split(middle_divided_chunk_2[0]);
-
- let bottom_chunks = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
- .split(vertical_chunks[2]);
-
- // Component specific chunks
- let cpu_chunk = Layout::default()
- .direction(Direction::Horizontal)
- .margin(0)
- .constraints(
- if app_state.left_legend {
- [Constraint::Percentage(15), Constraint::Percentage(85)]
- } else {
- [Constraint::Percentage(85), Constraint::Percentage(15)]
- }
- .as_ref(),
- )
- .split(vertical_chunks[0]);
-
- let network_chunk = Layout::default()
- .direction(Direction::Vertical)
- .margin(0)
- .constraints(
- if (bottom_chunks[0].height as f64 * 0.25) as u16 >= 4 {
- [Constraint::Percentage(75), Constraint::Percentage(25)]
- } else {
- let required = if bottom_chunks[0].height < 10 {
- bottom_chunks[0].height / 2
- } else {
- 5
- };
- let remaining = bottom_chunks[0].height - required;
- [Constraint::Length(remaining), Constraint::Length(required)]
- }
- .as_ref(),
- )
- .split(bottom_chunks[0]);
-
- // Default chunk index based on left or right legend setting
- let legend_index = if app_state.left_legend { 0 } else { 1 };
- let graph_index = if app_state.left_legend { 1 } else { 0 };
-
- // Set up blocks and their components
- // CPU graph
- draw_cpu_graph(&mut f, &app_state, cpu_chunk[graph_index]);
-
- // CPU legend
- draw_cpu_legend(&mut f, app_state, cpu_chunk[legend_index]);
-
- //Memory usage graph
- draw_memory_graph(&mut f, &app_state, middle_chunks[0]);
+ // TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases
+ let vertical_chunks = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(1)
+ .constraints(
+ [
+ Constraint::Percentage(30),
+ Constraint::Percentage(37),
+ Constraint::Percentage(33),
+ ]
+ .as_ref(),
+ )
+ .split(f.size());
- // Network graph
- draw_network_graph(&mut f, &app_state, network_chunk[0]);
+ let middle_chunks = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(60), Constraint::Percentage(40)].as_ref())
+ .split(vertical_chunks[1]);
- draw_network_labels(&mut f, app_state, network_chunk[1]);
+ let middle_divided_chunk_2 = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(middle_chunks[1]);
- // Temperature table
- draw_temp_table(&mut f, app_state, middle_divided_chunk_2[0]);
+ let bottom_chunks = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
+ .split(vertical_chunks[2]);
- // Disk usage table
- draw_disk_table(&mut f, app_state, middle_divided_chunk_2[1]);
+ // Component specific chunks
+ let cpu_chunk = Layout::default()
+ .direction(Direction::Horizontal)
+ .margin(0)
+ .constraints(
+ if app_state.left_legend {
+ [Constraint::Percentage(15), Constraint::Percentage(85)]
+ } else {
+ [Constraint::Percentage(85), Constraint::Percentage(15)]
+ }
+ .as_ref(),
+ )
+ .split(vertical_chunks[0]);
- // Processes table
- if app_state.is_searching() {
- let processes_chunk = Layout::default()
+ let network_chunk = Layout::default()
.direction(Direction::Vertical)
.margin(0)
.constraints(
- if (bottom_chunks[1].height as f64 * 0.25) as u16 >= 4 {
+ if (bottom_chunks[0].height as f64 * 0.25) as u16 >= 4 {
[Constraint::Percentage(75), Constraint::Percentage(25)]
} else {
- let required = if bottom_chunks[1].height < 10 {
- bottom_chunks[1].height / 2
+ let required = if bottom_chunks[0].height < 10 {
+ bottom_chunks[0].height / 2
} else {
5
};
- let remaining = bottom_chunks[1].height - required;
+ let remaining = bottom_chunks[0].height - required;
[Constraint::Length(remaining), Constraint::Length(required)]
}
.as_ref(),
)
- .split(bottom_chunks[1]);
+ .split(bottom_chunks[0]);
- draw_processes_table(&mut f, app_state, processes_chunk[0]);
- draw_search_field(&mut f, app_state, processes_chunk[1]);
- } else {
- draw_processes_table(&mut f, app_state, bottom_chunks[1]);
- }
- }
- })?;
+ // Default chunk index based on left or right legend setting
+ let legend_index = if app_state.left_legend { 0 } else { 1 };
+ let graph_index = if app_state.left_legend { 1 } else { 0 };
- Ok(())
-}
+ // Set up blocks and their components
+ // CPU graph
+ self.draw_cpu_graph(&mut f, &app_state, cpu_chunk[graph_index]);
+
+ // CPU legend
+ self.draw_cpu_legend(&mut f, app_state, cpu_chunk[legend_index]);
+
+ //Memory usage graph
+ self.draw_memory_graph(&mut f, &app_state, middle_chunks[0]);
+
+ // Network graph
+ self.draw_network_graph(&mut f, &app_state, network_chunk[0]);
+
+ self.draw_network_labels(&mut f, app_state, network_chunk[1]);
+
+ // Temperature table
+ self.draw_temp_table(&mut f, app_state, middle_divided_chunk_2[0]);
+
+ // Disk usage table
+ self.draw_disk_table(&mut f, app_state, middle_divided_chunk_2[1]);
+
+ // Processes table
+ if app_state.is_searching() {
+ let processes_chunk = Layout::default()
+ .direction(Direction::Vertical)
+ .margin(0)
+ .constraints(
+ if (bottom_chunks[1].height as f64 * 0.25) as u16 >= 4 {
+ [Constraint::Percentage(75), Constraint::Percentage(25)]
+ } else {
+ let required = if bottom_chunks[1].height < 10 {
+ bottom_chunks[1].height / 2
+ } else {
+ 5
+ };
+ let remaining = bottom_chunks[1].height - required;
+ [Constraint::Length(remaining), Constraint::Length(required)]
+ }
+ .as_ref(),
+ )
+ .split(bottom_chunks[1]);
+
+ self.draw_processes_table(&mut f, app_state, processes_chunk[0]);
+ self.draw_search_field(&mut f, app_state, processes_chunk[1]);
+ } else {
+ self.draw_processes_table(&mut f, app_state, bottom_chunks[1]);
+ }
+ }
+ })?;
-fn draw_cpu_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect) {
- let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data;
-
- // CPU usage graph
- let x_axis: Axis<String> = Axis::default()
- .style(Style::default().fg(GRAPH_COLOUR))
- .bounds([0.0, constants::TIME_STARTS_FROM as f64]);
- let y_axis = Axis::default()
- .style(Style::default().fg(GRAPH_COLOUR))
- .bounds([-0.5, 100.5])
- .labels(&["0%", "100%"]);
-
- let mut dataset_vector: Vec<Dataset> = Vec::new();
- let mut cpu_entries_vec: Vec<(Style, Vec<(f64, f64)>)> = Vec::new();
-
- for (i, cpu) in cpu_data.iter().enumerate() {
- cpu_entries_vec.push((
- Style::default().fg(COLOUR_LIST[(i) % COLOUR_LIST.len()]),
- cpu.cpu_data
- .iter()
- .map(<(f64, f64)>::from)
- .collect::<Vec<_>>(),
- ));
+ Ok(())
}
- if app_state.show_average_cpu {
- if let Some(avg_cpu_entry) = cpu_data.first() {
+ fn draw_cpu_graph<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect,
+ ) {
+ let cpu_data: &[ConvertedCpuData] = &app_state.canvas_data.cpu_data;
+
+ // CPU usage graph
+ let x_axis: Axis<String> = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([0.0, constants::TIME_STARTS_FROM as f64]);
+ let y_axis = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([-0.5, 100.5])
+ .labels(&["0%", "100%"]);
+
+ let mut dataset_vector: Vec<Dataset> = Vec::new();
+ let mut cpu_entries_vec: Vec<(Style, Vec<(f64, f64)>)> = Vec::new();
+
+ for (i, cpu) in cpu_data.iter().enumerate() {
cpu_entries_vec.push((
- Style::default().fg(COLOUR_LIST[0]),
- avg_cpu_entry
- .cpu_data
+ Style::default().fg(COLOUR_LIST[(i) % COLOUR_LIST.len()]),
+ cpu.cpu_data
.iter()
.map(<(f64, f64)>::from)
.collect::<Vec<_>>(),
));
}
+
+ if app_state.show_average_cpu {
+ if let Some(avg_cpu_entry) = cpu_data.first() {
+ cpu_entries_vec.push((
+ Style::default().fg(COLOUR_LIST[0]),
+ avg_cpu_entry
+ .cpu_data
+ .iter()
+ .map(<(f64, f64)>::from)
+ .collect::<Vec<_>>(),
+ ));
+ }
+ }
+
+ for cpu_entry in &cpu_entries_vec {
+ dataset_vector.push(
+ Dataset::default()
+ .marker(if app_state.use_dot {
+ Marker::Dot
+ } else {
+ Marker::Braille
+ })
+ .style(cpu_entry.0)
+ .data(&(cpu_entry.1)),
+ );
+ }
+
+ Chart::default()
+ .block(
+ Block::default()
+ .title("CPU")
+ .borders(Borders::ALL)
+ .border_style(match app_state.current_widget_selected {
+ app::WidgetPosition::Cpu => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
+ }),
+ )
+ .x_axis(x_axis)
+ .y_axis(y_axis)
+ .datasets(&dataset_vector)
+ .render(f, draw_loc);
}
- for cpu_entry in &cpu_entries_vec {
- dataset_vector.push(
- Dataset::default()
- .marker(if app_state.use_dot {
- Marker::Dot
- } else {
- Marker::Braille
- })
- .style(cpu_entry.0)
- .data(&(cpu_entry.1)),
+ fn draw_cpu_legend<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect,
+ ) {
+ let cpu_data: &[ConvertedCpuData] = &(app_state.canvas_data.cpu_data);
+
+ let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
+ let start_position = get_start_position(
+ num_rows,
+ &(app_state.scroll_direction),
+ &mut app_state.previous_cpu_table_position,
+ app_state.currently_selected_cpu_table_position,
);
- }
- Chart::default()
- .block(
- Block::default()
- .title("CPU")
- .borders(Borders::ALL)
- .border_style(match app_state.current_widget_selected {
- app::WidgetPosition::Cpu => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
- _ => *CANVAS_BORDER_STYLE,
- }),
- )
- .x_axis(x_axis)
- .y_axis(y_axis)
- .datasets(&dataset_vector)
- .render(f, draw_loc);
-}
+ let sliced_cpu_data = (&cpu_data[start_position as usize..]).to_vec();
+ let mut stringified_cpu_data: Vec<Vec<String>> = Vec::new();
-fn draw_cpu_legend<B: backend::Backend>(
- f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect,
-) {
- let cpu_data: &[ConvertedCpuData] = &(app_state.canvas_data.cpu_data);
-
- let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
- let start_position = get_start_position(
- num_rows,
- &(app_state.scroll_direction),
- &mut app_state.previous_cpu_table_position,
- app_state.currently_selected_cpu_table_position,
- );
-
- let sliced_cpu_data = (&cpu_data[start_position as usize..]).to_vec();
- let mut stringified_cpu_data: Vec<Vec<String>> = Vec::new();
-
- for cpu in sliced_cpu_data {
- if let Some(cpu_data) = cpu.cpu_data.last() {
- stringified_cpu_data.push(vec![
- cpu.cpu_name.clone(),
- format!("{:.0}%", cpu_data.usage.round()),
- ]);
+ for cpu in sliced_cpu_data {
+ if let Some(cpu_data) = cpu.cpu_data.last() {
+ stringified_cpu_data.push(vec![
+ cpu.cpu_name.clone(),
+ format!("{:.0}%", cpu_data.usage.round()),
+ ]);
+ }
}
- }
- let mut cpu_row_counter: i64 = 0;
-
- let cpu_rows = stringified_cpu_data
- .iter()
- .enumerate()
- .map(|(itx, cpu_string_row)| {
- Row::StyledData(
- cpu_string_row.iter(),
- match app_state.current_widget_selected {
- app::WidgetPosition::Cpu => {
- if cpu_row_counter as u64
- == app_state.currently_selected_cpu_table_position - start_position
- {
- cpu_row_counter = -1;
- Style::default().fg(Color::Black).bg(Color::Cyan)
- } else {
- if cpu_row_counter >= 0 {
- cpu_row_counter += 1;
+ let mut cpu_row_counter: i64 = 0;
+
+ let cpu_rows = stringified_cpu_data
+ .iter()
+ .enumerate()
+ .map(|(itx, cpu_string_row)| {
+ Row::StyledData(
+ cpu_string_row.iter(),
+ match app_state.current_widget_selected {
+ app::WidgetPosition::Cpu => {
+ if cpu_row_counter as u64
+ == app_state.currently_selected_cpu_table_position - start_position
+ {
+ cpu_row_counter = -1;
+ Style::default().fg(Color::Black).bg(Color::Cyan)
+ } else {
+ if cpu_row_counter >= 0 {
+ cpu_row_counter += 1;
+ }
+ Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()])
}
- Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()])
}
- }
- _ => Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()]),
+ _ => Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()]),
+ },
+ )
+ });
+
+ // Calculate widths
+ let width = f64::from(draw_loc.width);
+ let width_ratios = vec![0.5, 0.5];
+ let variable_intrinsic_results =
+ get_variable_intrinsic_widths(width as u16, &width_ratios, &CPU_LEGEND_HEADER_LENS);
+ let intrinsic_widths: Vec<u16> =
+ ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
+
+ // Draw
+ Table::new(CPU_LEGEND_HEADER.iter(), cpu_rows)
+ .block(Block::default().borders(Borders::ALL).border_style(
+ match app_state.current_widget_selected {
+ app::WidgetPosition::Cpu => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
},
+ ))
+ .header_style(Style::default().fg(TABLE_HEADER_COLOUR))
+ .widths(
+ &(intrinsic_widths
+ .into_iter()
+ .map(|calculated_width| Constraint::Length(calculated_width as u16))
+ .collect::<Vec<_>>()),
+ )
+ .render(f, draw_loc);
+ }
+
+ #[allow(dead_code)]
+ fn draw_memory_table<B: backend::Backend>(
+ f: &mut Frame<B>, app_state: &app::App, memory_entry: Vec<String>, swap_entry: Vec<String>,
+ draw_loc: Rect,
+ ) {
+ // Calculate widths
+ let width = f64::from(draw_loc.width);
+ let width_ratios = [0.2, 0.4, 0.4];
+ let variable_intrinsic_results =
+ get_variable_intrinsic_widths(width as u16, &width_ratios, &MEM_HEADERS_LENS);
+ let intrinsic_widths: Vec<u16> =
+ ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
+
+ let mem_rows = vec![memory_entry, swap_entry];
+ let mapped_mem_rows = mem_rows.iter().enumerate().map(|(itx, val)| {
+ Row::StyledData(
+ val.iter(),
+ Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()]),
)
});
- // Calculate widths
- let width = f64::from(draw_loc.width);
- let width_ratios = vec![0.5, 0.5];
- let variable_intrinsic_results =
- get_variable_intrinsic_widths(width as u16, &width_ratios, &CPU_LEGEND_HEADER_LENS);
- let intrinsic_widths: Vec<u16> =
- ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
+ // Draw
+ Table::new(MEM_HEADERS.iter(), mapped_mem_rows)
+ .block(Block::default().borders(Borders::ALL).border_style(
+ match app_state.current_widget_selected {
+ app::WidgetPosition::Mem => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
+ },
+ ))
+ .header_style(Style::default().fg(TABLE_HEADER_COLOUR))
+ .widths(
+ &(intrinsic_widths
+ .into_iter()
+ .map(|calculated_width| Constraint::Length(calculated_width as u16))
+ .collect::<Vec<_>>()),
+ )
+ .render(f, draw_loc);
+ }
- // Draw
- Table::new(CPU_LEGEND_HEADER.iter(), cpu_rows)
- .block(Block::default().borders(Borders::ALL).border_style(
- match app_state.current_widget_selected {
- app::WidgetPosition::Cpu => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
- _ => *CANVAS_BORDER_STYLE,
- },
- ))
- .header_style(Style::default().fg(TABLE_HEADER_COLOUR))
- .widths(
- &(intrinsic_widths
- .into_iter()
- .map(|calculated_width| Constraint::Length(calculated_width as u16))
- .collect::<Vec<_>>()),
- )
- .render(f, draw_loc);
-}
+ fn draw_memory_graph<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect,
+ ) {
+ let mem_data: &[(f64, f64)] = &(app_state.canvas_data.mem_data);
+ let swap_data: &[(f64, f64)] = &(app_state.canvas_data.swap_data);
+
+ let x_axis: Axis<String> = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([0.0, constants::TIME_STARTS_FROM as f64]);
+
+ // Offset as the zero value isn't drawn otherwise...
+ let y_axis: Axis<&str> = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([-0.5, 100.5])
+ .labels(&["0%", "100%"]);
+
+ let mut mem_canvas_vec: Vec<Dataset> = vec![Dataset::default()
+ .name(&app_state.canvas_data.mem_label)
+ .marker(if app_state.use_dot {
+ Marker::Dot
+ } else {
+ Marker::Braille
+ })
+ .style(Style::default().fg(COLOUR_LIST[0]))
+ .data(&mem_data)];
+
+ if !(&swap_data).is_empty() {
+ mem_canvas_vec.push(
+ Dataset::default()
+ .name(&app_state.canvas_data.swap_label)
+ .marker(if app_state.use_dot {
+ Marker::Dot
+ } else {
+ Marker::Braille
+ })
+ .style(Style::default().fg(COLOUR_LIST[1]))
+ .data(&swap_data),
+ );
+ }
-#[allow(dead_code)]
-fn draw_memory_table<B: backend::Backend>(
- f: &mut Frame<B>, app_state: &app::App, memory_entry: Vec<String>, swap_entry: Vec<String>,
- draw_loc: Rect,
-) {
- // Calculate widths
- let width = f64::from(draw_loc.width);
- let width_ratios = [0.2, 0.4, 0.4];
- let variable_intrinsic_results =
- get_variable_intrinsic_widths(width as u16, &width_ratios, &MEM_HEADERS_LENS);
- let intrinsic_widths: Vec<u16> =
- ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
-
- let mem_rows = vec![memory_entry, swap_entry];
- let mapped_mem_rows = mem_rows.iter().enumerate().map(|(itx, val)| {
- Row::StyledData(
- val.iter(),
- Style::default().fg(COLOUR_LIST[itx % COLOUR_LIST.len()]),
- )
- });
+ Chart::default()
+ .block(
+ Block::default()
+ .title("Memory")
+ .borders(Borders::ALL)
+ .border_style(match app_state.current_widget_selected {
+ app::WidgetPosition::Mem => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
+ }),
+ )
+ .x_axis(x_axis)
+ .y_axis(y_axis)
+ .datasets(&mem_canvas_vec)
+ .render(f, draw_loc);
+ }
+
+ fn draw_network_graph<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect,
+ ) {
+ 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 x_axis: Axis<String> = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([0.0, 60_000.0]);
+ let y_axis = Axis::default()
+ .style(Style::default().fg(GRAPH_COLOUR))
+ .bounds([-0.5, 30_f64])
+ .labels(&["0B", "1KiB", "1MiB", "1GiB"]);
+ Chart::default()
+ .block(
+ Block::default()
+ .title("Network")
+ .borders(Borders::ALL)
+ .border_style(match app_state.current_widget_selected {
+ app::WidgetPosition::Network => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
+ }),
+ )
+ .x_axis(x_axis)
+ .y_axis(y_axis)
+ .datasets(&[
+ Dataset::default()
+ .name("RX")
+ .marker(if app_state.use_dot {
+ Marker::Dot
+ } else {
+ Marker::Braille
+ })
+ .style(Style::default().fg(COLOUR_LIST[0]))
+ .data(&network_data_rx),
+ Dataset::default()
+ .name("TX")
+ .marker(if app_state.use_dot {
+ Marker::Dot
+ } else {
+ Marker::Braille
+ })
+ .style(Style::default().fg(COLOUR_LIST[1]))
+ .data(&network_data_tx),
+ ])
+ .render(f, draw_loc);
+ }
+
+ fn draw_network_labels<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect,
+ ) {
+ let rx_display: String = app_state.canvas_data.rx_display.clone();
+ let tx_display: String = app_state.canvas_data.tx_display.clone();
+ let total_rx_display: String = app_state.canvas_data.total_rx_display.clone();
+ let total_tx_display: String = app_state.canvas_data.total_tx_display.clone();
+
+ // Gross but I need it to work...
+ let total_network = if cfg!(not(target_os = "windows")) {
+ vec![vec![
+ rx_display,
+ tx_display,
+ total_rx_display,
+ total_tx_display,
+ ]]
+ } else {
+ vec![vec![rx_display, tx_display]]
+ };
+ let mapped_network = total_network.iter().map(|val| Row::Data(val.iter()));
+
+ // Calculate widths
+ let width_ratios: Vec<f64>;
+ let lens: &Vec<usize>;
+ let width = f64::from(draw_loc.width);
- // Draw
- Table::new(MEM_HEADERS.iter(), mapped_mem_rows)
+ if cfg!(not(target_os = "windows")) {
+ width_ratios = vec![0.25, 0.25, 0.25, 0.25];
+ lens = &NON_WINDOWS_NETWORK_HEADERS_LENS;
+ } else {
+ width_ratios = vec![0.25, 0.25];
+ lens = &WINDOWS_NETWORK_HEADERS_LENS;
+ }
+ let variable_intrinsic_results =
+ get_variable_intrinsic_widths(width as u16, &width_ratios, lens);
+ let intrinsic_widths: Vec<u16> =
+ ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
+
+ // Draw
+ Table::new(
+ // TODO: [OPT] Feels like I can optimize this and avoid multiple to_vec calls?
+ if cfg!(not(target_os = "windows")) {
+ NON_WINDOWS_NETWORK_HEADERS.to_vec()
+ } else {
+ WINDOWS_NETWORK_HEADERS.to_vec()
+ }
+ .iter(),
+ mapped_network,
+ )
.block(Block::default().borders(Borders::ALL).border_style(
match app_state.current_widget_selected {
- app::WidgetPosition::Mem => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ app::WidgetPosition::Network => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
_ => *CANVAS_BORDER_STYLE,
},
))
@@ -588,547 +758,385 @@ fn draw_memory_table<B: backend::Backend>(
.collect::<Vec<_>>()),
)
.render(f, draw_loc);
-}
+ }
-fn draw_memory_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::App, draw_loc: Rect) {
- let mem_data: &[(f64, f64)] = &(app_state.canvas_data.mem_data);
- let swap_data: &[(f64, f64)] = &(app_state.canvas_data.swap_data);
+ fn draw_temp_table<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect,
+ ) {
+ let temp_sensor_data: &[Vec<String>] = &(app_state.canvas_data.temp_sensor_data);
+
+ let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
+ let start_position = get_start_position(
+ num_rows,
+ &(app_state.scroll_direction),
+ &mut app_state.previous_temp_position,
+ app_state.currently_selected_temperature_position,
+ );
+
+ let sliced_vec: Vec<Vec<String>> = (&temp_sensor_data[start_position as usize..]).to_vec();
+ let mut temp_row_counter: i64 = 0;
- let x_axis: Axis<String> = Axis::default()
- .style(Style::default().fg(GRAPH_COLOUR))
- .bounds([0.0, constants::TIME_STARTS_FROM as f64]);
+ let temperature_rows = sliced_vec.iter().map(|temp_row| {
+ Row::StyledData(
+ temp_row.iter(),
+ match app_state.current_widget_selected {
+ app::WidgetPosition::Temp => {
+ if temp_row_counter as u64
+ == app_state.currently_selected_temperature_position - start_position
+ {
+ temp_row_counter = -1;
+ Style::default().fg(Color::Black).bg(Color::Cyan)
+ } else {
+ if temp_row_counter >= 0 {
+ temp_row_counter += 1;
+ }
+ Style::default().fg(TEXT_COLOUR)
+ }
+ }
+ _ => Style::default().fg(TEXT_COLOUR),
+ },
+ )
+ });
- // Offset as the zero value isn't drawn otherwise...
- let y_axis: Axis<&str> = Axis::default()
- .style(Style::default().fg(GRAPH_COLOUR))
- .bounds([-0.5, 100.5])
- .labels(&["0%", "100%"]);
+ // Calculate widths
+ let width = f64::from(draw_loc.width);
+ let width_ratios = [0.5, 0.5];
+ let variable_intrinsic_results =
+ get_variable_intrinsic_widths(width as u16, &width_ratios, &TEMP_HEADERS_LENS);
+ let intrinsic_widths: Vec<u16> =
+ ((variable_intrinsic_results.0)[0..variable_intrinsic_results.1]).to_vec();
+
+ // Draw
+ Table::new(TEMP_HEADERS.iter(), temperature_rows)
+ .block(
+ Block::default()
+ .title("Temperatures")
+ .borders(Borders::ALL)
+ .border_style(match app_state.current_widget_selected {
+ app::WidgetPosition::Temp => *CANVAS_HIGHLIGHTED_BORDER_STYLE,
+ _ => *CANVAS_BORDER_STYLE,
+ }),
+ )
+ .header_style(Style::default().fg(TABLE_HEADER_COLOUR))
+ .widths(
+ &(intrinsic_widths
+ .into_iter()
+ .map(|calculated_width| Constraint::Length(calculated_width as u16))
+ .collect::<Vec<_>>()),
+ )
+ .render(f, draw_loc);
+ }
- let mut mem_canvas_vec: Vec<Dataset> = vec![Dataset::default()
- .name(&app_state.canvas_data.mem_label)
- .marker(if app_state.use_dot {
- Marker::Dot
- } else {
- Marker::Braille
- })
- .style(Style::default().fg(COLOUR_LIST[0]))
- .data(&mem_data)];
-
- if !(&swap_data).is_empty() {
- mem_canvas_vec.push(
- Dataset::default()
- .name(&app_state.canvas_data.swap_label)
- .marker(if app_state.use_dot {
- Marker::Dot
- } else {
- Marker::Braille
- })
- .style(Style::default().fg(COLOUR_LIST[1]))
- .data(&swap_data),
+ fn draw_disk_table<B: backend::Backend>(
+ &self, f: &mut Frame<B>, app_state: &mut app::App, draw_loc: Rect,
+ ) {
+ let disk