From 7f34061e68ee7b04f94d76fc1e4c893a13b8a876 Mon Sep 17 00:00:00 2001 From: ClementTsang Date: Sun, 1 Mar 2020 23:53:49 -0500 Subject: [PATCH] Added proper navigation for basic mode. --- src/app.rs | 148 +++++++++++++++++------- src/canvas.rs | 310 ++++++++++++++++++++++++++++++-------------------- src/main.rs | 6 +- 3 files changed, 301 insertions(+), 163 deletions(-) diff --git a/src/app.rs b/src/app.rs index 8cf55492..f3a98a99 100644 --- a/src/app.rs +++ b/src/app.rs @@ -23,6 +23,21 @@ pub enum WidgetPosition { Network, Process, ProcessSearch, + BasicCpu, + BasicMem, + BasicNet, +} + +impl WidgetPosition { + pub fn is_widget_table(self) -> bool { + match self { + WidgetPosition::Disk + | WidgetPosition::Process + | WidgetPosition::ProcessSearch + | WidgetPosition::Temp => true, + _ => false, + } + } } #[derive(Debug)] @@ -244,6 +259,7 @@ pub struct App { pub update_process_gui: bool, pub app_scroll_positions: AppScrollState, pub current_widget_selected: WidgetPosition, + pub last_basic_table_widget_selected: WidgetPosition, awaiting_second_char: bool, second_char: Option, pub dd_err: Option, @@ -277,6 +293,11 @@ impl App { process_sorting_reverse: true, update_process_gui: false, current_widget_selected, + last_basic_table_widget_selected: if current_widget_selected.is_widget_table() { + current_widget_selected + } else { + WidgetPosition::Process + }, app_scroll_positions: AppScrollState::default(), awaiting_second_char: false, second_char: None, @@ -568,10 +589,6 @@ impl App { self.process_search_state.search_state.char_cursor_position } - pub fn move_basic_left(&mut self) {} - - pub fn move_basic_right(&mut self) {} - /// One of two functions allowed to run while in a dialog... pub fn on_enter(&mut self) { if self.delete_dialog_state.is_showing_dd { @@ -1051,7 +1068,7 @@ impl App { self.to_delete_process_list.clone() } - // For now, these are hard coded --- in the future, they shouldn't be! + // TODO: [MODULARITY] Do NOT hard code this in thu future! // // General idea for now: // CPU -(down)> MEM @@ -1063,13 +1080,24 @@ impl App { // PROC_SEARCH -(up)> PROC, -(left)> Network pub fn move_widget_selection_left(&mut self) { if !self.is_in_dialog() && !self.is_expanded { - self.current_widget_selected = match self.current_widget_selected { - WidgetPosition::Process => WidgetPosition::Network, - WidgetPosition::ProcessSearch => WidgetPosition::Network, - WidgetPosition::Disk => WidgetPosition::Mem, - WidgetPosition::Temp => WidgetPosition::Mem, - _ => self.current_widget_selected, - }; + if self.app_config_fields.use_basic_mode { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::BasicNet => WidgetPosition::BasicMem, + WidgetPosition::Process => WidgetPosition::Disk, + WidgetPosition::ProcessSearch => WidgetPosition::Disk, + WidgetPosition::Disk => WidgetPosition::Temp, + WidgetPosition::Temp => WidgetPosition::Process, + _ => self.current_widget_selected, + }; + } else { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::Process => WidgetPosition::Network, + WidgetPosition::ProcessSearch => WidgetPosition::Network, + WidgetPosition::Disk => WidgetPosition::Mem, + WidgetPosition::Temp => WidgetPosition::Mem, + _ => self.current_widget_selected, + }; + } } self.reset_multi_tap_keys(); @@ -1077,11 +1105,22 @@ impl App { pub fn move_widget_selection_right(&mut self) { if !self.is_in_dialog() && !self.is_expanded { - self.current_widget_selected = match self.current_widget_selected { - WidgetPosition::Mem => WidgetPosition::Temp, - WidgetPosition::Network => WidgetPosition::Process, - _ => self.current_widget_selected, - }; + if self.app_config_fields.use_basic_mode { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::BasicMem => WidgetPosition::BasicNet, + WidgetPosition::Process => WidgetPosition::Temp, + WidgetPosition::ProcessSearch => WidgetPosition::Temp, + WidgetPosition::Disk => WidgetPosition::Process, + WidgetPosition::Temp => WidgetPosition::Disk, + _ => self.current_widget_selected, + }; + } else { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::Mem => WidgetPosition::Temp, + WidgetPosition::Network => WidgetPosition::Process, + _ => self.current_widget_selected, + }; + } } self.reset_multi_tap_keys(); @@ -1089,15 +1128,30 @@ impl App { pub fn move_widget_selection_up(&mut self) { if !self.is_in_dialog() && !self.is_expanded { - self.current_widget_selected = match self.current_widget_selected { - WidgetPosition::Mem => WidgetPosition::Cpu, - WidgetPosition::Network => WidgetPosition::Mem, - WidgetPosition::Process => WidgetPosition::Disk, - WidgetPosition::ProcessSearch => WidgetPosition::Process, - WidgetPosition::Temp => WidgetPosition::Cpu, - WidgetPosition::Disk => WidgetPosition::Temp, - _ => self.current_widget_selected, - }; + if self.app_config_fields.use_basic_mode { + if self.current_widget_selected.is_widget_table() { + self.last_basic_table_widget_selected = self.current_widget_selected; + } + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::BasicMem => WidgetPosition::BasicCpu, + WidgetPosition::BasicNet => WidgetPosition::BasicCpu, + WidgetPosition::Process => WidgetPosition::BasicMem, + WidgetPosition::ProcessSearch => WidgetPosition::Process, + WidgetPosition::Temp => WidgetPosition::BasicMem, + WidgetPosition::Disk => WidgetPosition::BasicMem, + _ => self.current_widget_selected, + }; + } else { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::Mem => WidgetPosition::Cpu, + WidgetPosition::Network => WidgetPosition::Mem, + WidgetPosition::Process => WidgetPosition::Disk, + WidgetPosition::ProcessSearch => WidgetPosition::Process, + WidgetPosition::Temp => WidgetPosition::Cpu, + WidgetPosition::Disk => WidgetPosition::Temp, + _ => self.current_widget_selected, + }; + } } else if self.is_expanded { self.current_widget_selected = match self.current_widget_selected { WidgetPosition::ProcessSearch => WidgetPosition::Process, @@ -1110,20 +1164,36 @@ impl App { pub fn move_widget_selection_down(&mut self) { if !self.is_in_dialog() && !self.is_expanded { - self.current_widget_selected = match self.current_widget_selected { - WidgetPosition::Cpu => WidgetPosition::Mem, - WidgetPosition::Mem => WidgetPosition::Network, - WidgetPosition::Temp => WidgetPosition::Disk, - WidgetPosition::Disk => WidgetPosition::Process, - WidgetPosition::Process => { - if self.is_searching() { - WidgetPosition::ProcessSearch - } else { - WidgetPosition::Process + if self.app_config_fields.use_basic_mode { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::BasicMem => self.last_basic_table_widget_selected, + WidgetPosition::BasicNet => self.last_basic_table_widget_selected, + WidgetPosition::BasicCpu => WidgetPosition::BasicMem, + WidgetPosition::Process => { + if self.is_searching() { + WidgetPosition::ProcessSearch + } else { + WidgetPosition::Process + } } - } - _ => self.current_widget_selected, - }; + _ => self.current_widget_selected, + }; + } else { + self.current_widget_selected = match self.current_widget_selected { + WidgetPosition::Cpu => WidgetPosition::Mem, + WidgetPosition::Mem => WidgetPosition::Network, + WidgetPosition::Temp => WidgetPosition::Disk, + WidgetPosition::Disk => WidgetPosition::Process, + WidgetPosition::Process => { + if self.is_searching() { + WidgetPosition::ProcessSearch + } else { + WidgetPosition::Process + } + } + _ => self.current_widget_selected, + }; + } } else if self.is_expanded { self.current_widget_selected = match self.current_widget_selected { WidgetPosition::Process => { diff --git a/src/canvas.rs b/src/canvas.rs index 9f32f97b..7b228908 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -151,6 +151,20 @@ impl Painter { ); } + pub fn draw_specific_table( + &self, f: &mut Frame<'_, B>, app_state: &mut app::App, draw_loc: Rect, draw_border: bool, + widget_selected: WidgetPosition, + ) { + match widget_selected { + WidgetPosition::Process | WidgetPosition::ProcessSearch => { + self.draw_process_and_search(f, app_state, draw_loc, draw_border) + } + WidgetPosition::Temp => self.draw_temp_table(f, app_state, draw_loc, draw_border), + WidgetPosition::Disk => self.draw_disk_table(f, app_state, draw_loc, draw_border), + _ => {} + } + } + // TODO: [REFACTOR] We should clean this up tbh // TODO: [FEATURE] Auto-resizing dialog sizes. #[allow(clippy::cognitive_complexity)] @@ -361,7 +375,7 @@ impl Painter { .constraints([Constraint::Percentage(100)].as_ref()) .split(f.size()); match &app_state.current_widget_selected { - WidgetPosition::Cpu => { + WidgetPosition::Cpu | WidgetPosition::BasicCpu=> { let cpu_chunk = Layout::default() .direction(Direction::Horizontal) .margin(0) @@ -389,7 +403,7 @@ impl Painter { self.draw_cpu_graph(&mut f, &app_state, cpu_chunk[graph_index]); self.draw_cpu_legend(&mut f, app_state, cpu_chunk[legend_index]); } - WidgetPosition::Mem => { + WidgetPosition::Mem | WidgetPosition::BasicMem => { self.draw_memory_graph(&mut f, &app_state, rect[0]); } WidgetPosition::Disk => { @@ -398,7 +412,7 @@ impl Painter { WidgetPosition::Temp => { self.draw_temp_table(&mut f, app_state, rect[0], true); } - WidgetPosition::Network => { + WidgetPosition::Network | WidgetPosition::BasicNet => { self.draw_network_graph(&mut f, &app_state, rect[0]); } WidgetPosition::Process | WidgetPosition::ProcessSearch => { @@ -431,7 +445,6 @@ impl Painter { 1 } ); - debug!("C: {}", cpu_height); let vertical_chunks = Layout::default() .direction(Direction::Vertical) .constraints([ @@ -448,11 +461,14 @@ impl Painter { Constraint::Percentage(50), ].as_ref()) .split(vertical_chunks[1]); - self.draw_basic_cpu(&mut f, app_state, vertical_chunks[0]); self.draw_basic_memory(&mut f, app_state, middle_chunks[0]); self.draw_basic_network(&mut f, app_state, middle_chunks[1]); - self.draw_process_and_search(&mut f, app_state, vertical_chunks[2], false); + if app_state.current_widget_selected.is_widget_table() { + self.draw_specific_table(&mut f, app_state, vertical_chunks[2], false, app_state.current_widget_selected); + } else { + self.draw_specific_table(&mut f, app_state, vertical_chunks[2], false, app_state.last_basic_table_widget_selected); + } } else { // TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases let vertical_chunks = Layout::default() @@ -1070,30 +1086,50 @@ impl Painter { ); result_title + } else if app_state.app_config_fields.use_basic_mode { + String::new() } else { " Temperatures ".to_string() }; - // Draw - Table::new(TEMP_HEADERS.iter(), temperature_rows) - .block( - Block::default() - .title(&title) - .title_style(if app_state.is_expanded { - self.colours.highlighted_border_style - } else { - self.colours.widget_title_style - }) - .borders(if draw_border { - Borders::ALL - } else { - Borders::NONE - }) - .border_style(match app_state.current_widget_selected { + let temp_block = if draw_border { + Block::default() + .title(&title) + .title_style(if app_state.is_expanded { + match app_state.current_widget_selected { app::WidgetPosition::Temp => 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 { + app::WidgetPosition::Temp => self.colours.highlighted_border_style, + _ => self.colours.border_style, + }) + } else { + match app_state.current_widget_selected { + app::WidgetPosition::Temp => 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 { + app::WidgetPosition::Temp => 0, + _ if !draw_border => 1, + _ => 0, + }) + .direction(Direction::Horizontal) + .split(draw_loc); + + // Draw + Table::new(TEMP_HEADERS.iter(), temperature_rows) + .block(temp_block) .header_style(self.colours.table_header_style) .widths( &(intrinsic_widths @@ -1101,7 +1137,7 @@ impl Painter { .map(|calculated_width| Constraint::Length(*calculated_width as u16)) .collect::>()), ) - .render(f, draw_loc); + .render(f, margined_draw_loc[0]); } fn draw_disk_table( @@ -1170,32 +1206,51 @@ impl Painter { " 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() }; - // Draw! - Table::new(DISK_HEADERS.iter(), disk_rows) - .block( - Block::default() - .title(&title) - .title_style(if app_state.is_expanded { - self.colours.highlighted_border_style - } else { - self.colours.widget_title_style - }) - .borders(if draw_border { - Borders::ALL - } else { - Borders::NONE - }) - .border_style(match app_state.current_widget_selected { + let disk_block = if draw_border { + Block::default() + .title(&title) + .title_style(if app_state.is_expanded { + match app_state.current_widget_selected { app::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 { + app::WidgetPosition::Disk => self.colours.highlighted_border_style, + _ => self.colours.border_style, + }) + } else { + match app_state.current_widget_selected { + app::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 { + app::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 @@ -1203,7 +1258,7 @@ impl Painter { .map(|calculated_width| Constraint::Length(*calculated_width as u16)) .collect::>()), ) - .render(f, draw_loc); + .render(f, margined_draw_loc[0]); } fn draw_search_field( @@ -1367,22 +1422,37 @@ impl Painter { } }; - Paragraph::new(search_text.iter()) - .block( - Block::default() - .borders(if draw_border { - Borders::ALL - } else { - Borders::NONE - }) - .title(&title) - .title_style(current_border_style) + let process_search_block = if draw_border { + Block::default() + .title(&title) + .title_style(current_border_style) + .borders(Borders::ALL) + .border_style(current_border_style) + } else { + match app_state.current_widget_selected { + app::WidgetPosition::ProcessSearch => Block::default() + .borders(*SIDE_BORDERS) .border_style(current_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 { + app::WidgetPosition::ProcessSearch => 0, + _ if !draw_border => 1, + _ => 0, + }) + .direction(Direction::Horizontal) + .split(draw_loc); + + Paragraph::new(search_text.iter()) + .block(process_search_block) .style(self.colours.text_style) .alignment(Alignment::Left) .wrap(false) - .render(f, draw_loc); + .render(f, margined_draw_loc[0]); } fn draw_processes_table( @@ -1580,7 +1650,7 @@ impl Painter { // Then, from this, split the row space across ALL columns. From there, generate // the desired lengths. - if let WidgetPosition::Cpu = app_state.current_widget_selected { + if let WidgetPosition::BasicCpu = app_state.current_widget_selected { Block::default() .borders(*SIDE_BORDERS) .border_style(self.colours.highlighted_border_style) @@ -1588,78 +1658,74 @@ impl Painter { } let num_cpus = cpu_data.len(); - if draw_loc.height > 0 { - let remaining_height = draw_loc.height as usize; - let required_columns = 4; + 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); + 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; + // +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; + let bar_length = remaining_width / REQUIRED_COLUMNS; - let cpu_bars = (0..num_cpus) + 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::>(); + + for (current_row, chunk) in chunks.iter().enumerate() { + let start_index = (current_row * remaining_height) as usize; + let end_index = min(start_index + remaining_height, num_cpus); + let cpu_column: Vec> = (start_index..end_index) .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(), + Text::Styled( + (&cpu_bars[cpu_index]).into(), + self.colours.cpu_colour_styles + [cpu_index as usize % self.colours.cpu_colour_styles.len()], ) }) .collect::>(); - for (current_row, chunk) in chunks.iter().enumerate() { - let start_index = (current_row * remaining_height) as usize; - let end_index = min(start_index + remaining_height, num_cpus); - let cpu_column: Vec> = (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::>(); + let margined_loc = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Percentage(100)].as_ref()) + .horizontal_margin(1) + .split(*chunk); - 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]); - } + Paragraph::new(cpu_column.iter()) + .block(Block::default()) + .render(f, margined_loc[0]); } } @@ -1674,7 +1740,7 @@ impl Painter { .horizontal_margin(1) .split(draw_loc); - if let WidgetPosition::Mem = app_state.current_widget_selected { + if let WidgetPosition::BasicMem = app_state.current_widget_selected { Block::default() .borders(*SIDE_BORDERS) .border_style(self.colours.highlighted_border_style) @@ -1738,7 +1804,7 @@ impl Painter { .horizontal_margin(1) .split(divided_loc[1]); - if let WidgetPosition::Network = app_state.current_widget_selected { + if let WidgetPosition::BasicNet = app_state.current_widget_selected { Block::default() .borders(*SIDE_BORDERS) .border_style(self.colours.highlighted_border_style) diff --git a/src/main.rs b/src/main.rs index 9fdc0242..8a4ab097 100644 --- a/src/main.rs +++ b/src/main.rs @@ -361,8 +361,10 @@ fn handle_key_event_or_break( KeyCode::Char('u') => app.clear_search(), KeyCode::Char('a') => app.skip_cursor_beginning(), KeyCode::Char('e') => app.skip_cursor_end(), - KeyCode::Char('h') => app.move_basic_left(), - KeyCode::Char('l') => app.move_basic_right(), + // KeyCode::Char('j') => {}, // Move down + // KeyCode::Char('k') => {}, // Move up + // KeyCode::Char('h') => {}, // Move right + // KeyCode::Char('l') => {}, // Move left // Can't do now, CTRL+BACKSPACE doesn't work and graphemes // are hard to iter while truncating last (eloquently). // KeyCode::Backspace => app.skip_word_backspace(),