diff options
author | Clement Tsang <34804052+ClementTsang@users.noreply.github.com> | 2020-02-16 19:50:34 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-16 19:50:34 -0500 |
commit | 683a3d3a259814e6aa9d4ce372dd990157364959 (patch) | |
tree | 947c18705f4a3c8e190eb4158c4723f79ed8e1fb | |
parent | 3224adf0473aae687a0fddffe4e443b46c4c6cce (diff) | |
parent | 65634f23d4af748c158151cb2ead13e861c2bc1a (diff) |
Merge pull request #9 from ClementTsang/add_graph_filtering
Add graph filtering
-rw-r--r-- | src/app.rs | 411 | ||||
-rw-r--r-- | src/canvas.rs | 154 | ||||
-rw-r--r-- | src/canvas/canvas_colours/colour_utils.rs | 3 | ||||
-rw-r--r-- | src/main.rs | 48 |
4 files changed, 431 insertions, 185 deletions
@@ -60,62 +60,63 @@ impl Default for AppScrollState { } } -/// AppSearchState only deals with the search's current settings and state. +/// AppSearchState deals with generic searching (I might do this in the future). pub struct AppSearchState { + is_enabled: bool, current_search_query: String, - searching_pid: bool, - ignore_case: bool, current_regex: std::result::Result<regex::Regex, regex::Error>, current_cursor_position: usize, - match_word: bool, - use_regex: bool, + pub is_invalid_or_blank_search: bool, } impl Default for AppSearchState { fn default() -> Self { AppSearchState { + is_enabled: false, current_search_query: String::default(), - searching_pid: false, - ignore_case: true, current_regex: BASE_REGEX.clone(), current_cursor_position: 0, - match_word: false, - use_regex: false, + is_invalid_or_blank_search: true, } } } -impl AppSearchState { +/// ProcessSearchState only deals with process' search's current settings and state. +pub struct ProcessSearchState { + pub search_state: AppSearchState, + pub is_searching_with_pid: bool, + pub is_ignoring_case: bool, + pub is_searching_whole_word: bool, + pub is_searching_with_regex: bool, +} + +impl Default for ProcessSearchState { + fn default() -> Self { + ProcessSearchState { + search_state: AppSearchState::default(), + is_searching_with_pid: false, + is_ignoring_case: true, + is_searching_whole_word: false, + is_searching_with_regex: false, + } + } +} + +impl ProcessSearchState { pub fn toggle_ignore_case(&mut self) { - self.ignore_case = !self.ignore_case; + self.is_ignoring_case = !self.is_ignoring_case; } pub fn toggle_search_whole_word(&mut self) { - self.match_word = !self.match_word; + self.is_searching_whole_word = !self.is_searching_whole_word; } pub fn toggle_search_regex(&mut self) { - self.use_regex = !self.use_regex; + self.is_searching_with_regex = !self.is_searching_with_regex; } pub fn toggle_search_with_pid(&mut self) { - self.searching_pid = !self.searching_pid; - } - - pub fn is_ignoring_case(&self) -> bool { - self.ignore_case - } - - pub fn is_searching_whole_word(&self) -> bool { - self.match_word - } - - pub fn is_searching_with_regex(&self) -> bool { - self.use_regex - } - - pub fn is_searching_with_pid(&self) -> bool { - self.searching_pid + self.is_searching_with_pid = !self.is_searching_with_pid; } } @@ -156,6 +157,61 @@ pub struct AppConfigFields { pub use_current_cpu_total: bool, } +/// Network specific +pub struct NetworkState { + pub is_showing_tray: bool, + pub is_showing_rx: bool, + pub is_showing_tx: bool, + pub zoom_level: f64, +} + +impl Default for NetworkState { + fn default() -> Self { + NetworkState { + is_showing_tray: false, + is_showing_rx: true, + is_showing_tx: true, + zoom_level: 100.0, + } + } +} + +/// CPU specific +pub struct CpuState { + pub is_showing_tray: bool, + pub zoom_level: f64, + pub core_show_vec: Vec<bool>, +} + +impl Default for CpuState { + fn default() -> Self { + CpuState { + is_showing_tray: false, + zoom_level: 100.0, + core_show_vec: Vec::new(), + } + } +} + +/// Memory specific +pub struct MemState { + pub is_showing_tray: bool, + pub is_showing_ram: bool, + pub is_showing_swap: bool, + pub zoom_level: f64, +} + +impl Default for MemState { + fn default() -> Self { + MemState { + is_showing_tray: false, + is_showing_ram: true, + is_showing_swap: true, + zoom_level: 100.0, + } + } +} + pub struct App { pub process_sorting_type: processes::ProcessSorting, pub process_sorting_reverse: bool, @@ -171,13 +227,15 @@ pub struct App { last_key_press: Instant, pub canvas_data: canvas::DisplayableData, enable_grouping: bool, - enable_searching: bool, pub data_collection: DataCollection, - pub search_state: AppSearchState, + pub process_search_state: ProcessSearchState, pub delete_dialog_state: AppDeleteDialogState, pub help_dialog_state: AppHelpDialogState, pub app_config_fields: AppConfigFields, pub is_expanded: bool, + pub cpu_state: CpuState, + pub mem_state: MemState, + pub net_state: NetworkState, } impl App { @@ -201,9 +259,8 @@ impl App { last_key_press: Instant::now(), canvas_data: canvas::DisplayableData::default(), enable_grouping: false, - enable_searching: false, data_collection: DataCollection::default(), - search_state: AppSearchState::default(), + process_search_state: ProcessSearchState::default(), delete_dialog_state: AppDeleteDialogState::default(), help_dialog_state: AppHelpDialogState::default(), app_config_fields: AppConfigFields { @@ -215,6 +272,9 @@ impl App { use_current_cpu_total, }, is_expanded: false, + cpu_state: CpuState::default(), + mem_state: MemState::default(), + net_state: NetworkState::default(), } } @@ -222,12 +282,12 @@ impl App { self.reset_multi_tap_keys(); self.help_dialog_state.is_showing_help = false; self.delete_dialog_state.is_showing_dd = false; - if self.enable_searching { + if self.process_search_state.search_state.is_enabled { self.current_widget_selected = WidgetPosition::Process; - self.enable_searching = false; + self.process_search_state.search_state.is_enabled = false; } - self.search_state.current_search_query = String::new(); - self.search_state.searching_pid = false; + self.process_search_state.search_state.current_search_query = String::new(); + self.process_search_state.is_searching_with_pid = false; self.to_delete_process_list = None; self.dd_err = None; } @@ -241,14 +301,37 @@ impl App { self.delete_dialog_state.is_on_yes = false; self.to_delete_process_list = None; self.dd_err = None; - } else if self.enable_searching { - self.current_widget_selected = WidgetPosition::Process; - self.enable_searching = false; + } else if self.is_filtering_or_searching() { + match self.current_widget_selected { + WidgetPosition::Process | WidgetPosition::ProcessSearch => { + if self.process_search_state.search_state.is_enabled { + self.current_widget_selected = WidgetPosition::Process; + self.process_search_state.search_state.is_enabled = false; + } + } + WidgetPosition::Cpu => { + self.cpu_state.is_showing_tray = false; + } + WidgetPosition::Mem => { + self.mem_state.is_showing_tray = false; + } + WidgetPosition::Network => { + self.net_state.is_showing_tray = false; + } + _ => {} + } } else if self.is_expanded { self.is_expanded = false; } } + fn is_filtering_or_searching(&self) -> bool { + self.cpu_state.is_showing_tray + || self.mem_state.is_showing_tray + || self.net_state.is_showing_tray + || self.process_search_state.search_state.is_enabled + } + fn reset_multi_tap_keys(&mut self) { self.awaiting_second_char = false; self.second_char = None; @@ -273,7 +356,7 @@ impl App { WidgetPosition::Process => self.toggle_grouping(), WidgetPosition::Disk => {} WidgetPosition::ProcessSearch => { - if self.search_state.is_searching_with_pid() { + if self.process_search_state.is_searching_with_pid { self.search_with_name(); } else { self.search_with_pid(); @@ -287,21 +370,48 @@ impl App { self.enable_grouping } - pub fn enable_searching(&mut self) { + pub fn on_space(&mut self) { + match self.current_widget_selected { + WidgetPosition::Cpu => { + let curr_posn = self + .app_scroll_positions + .cpu_scroll_state + .current_scroll_position; + if self.cpu_state.is_showing_tray + && curr_posn < self.data_collection.cpu_harvest.len() as u64 + { + self.cpu_state.core_show_vec[curr_posn as usize] = + !self.cpu_state.core_show_vec[curr_posn as usize]; + } + } + _ => {} + } + } + + pub fn on_slash(&mut self) { if !self.is_in_dialog() { match self.current_widget_selected { WidgetPosition::Process | WidgetPosition::ProcessSearch => { // Toggle on - self.enable_searching = true; + self.process_search_state.search_state.is_enabled = true; self.current_widget_selected = WidgetPosition::ProcessSearch; } + WidgetPosition::Cpu => { + self.cpu_state.is_showing_tray = true; + } + // WidgetPosition::Mem => { + // self.mem_state.is_showing_tray = true; + // } + // WidgetPosition::Network => { + // self.net_state.is_showing_tray = true; + // } _ => {} } } } pub fn is_searching(&self) -> bool { - self.enable_searching + self.process_search_state.search_state.is_enabled } pub fn is_in_search_widget(&self) -> bool { @@ -315,7 +425,7 @@ impl App { pub fn search_with_pid(&mut self) { if !self.is_in_dialog() && self.is_searching() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state.searching_pid = true; + self.process_search_state.is_searching_with_pid = true; } } } @@ -323,19 +433,19 @@ impl App { pub fn search_with_name(&mut self) { if !self.is_in_dialog() && self.is_searching() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state.searching_pid = false; + self.process_search_state.is_searching_with_pid = false; } } } pub fn get_current_search_query(&self) -> &String { - &self.search_state.current_search_query + &self.process_search_state.search_state.current_search_query } pub fn toggle_ignore_case(&mut self) { if !self.is_in_dialog() && self.is_searching() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state.toggle_ignore_case(); + self.process_search_state.toggle_ignore_case(); self.update_regex(); self.update_process_gui = true; } @@ -343,24 +453,43 @@ impl App { } pub fn update_regex(&mut self) { - self.search_state.current_regex = if self.search_state.current_search_query.is_empty() { + self.process_search_state.search_state.current_regex = if self + .process_search_state + .search_state + .current_search_query + .is_empty() + { + self.process_search_state + .search_state + .is_invalid_or_blank_search = true; BASE_REGEX.clone() } else { - let mut final_regex_string = self.search_state.current_search_query.clone(); + let mut final_regex_string = self + .process_search_state + .search_state + .current_search_query + .clone(); - if !self.search_state.is_searching_with_regex() { + if !self.process_search_state.is_searching_with_regex { final_regex_string = regex::escape(&final_regex_string); } - if self.search_state.is_searching_whole_word() { + if self.process_search_state.is_searching_whole_word { final_regex_string = format!("^{}$", final_regex_string); } - if self.search_state.is_ignoring_case() { + if self.process_search_state.is_ignoring_case { final_regex_string = format!("(?i){}", final_regex_string); } regex::Regex::new(&final_regex_string) }; + self.process_search_state + .search_state + .is_invalid_or_blank_search = self + .process_search_state + .search_state + .current_regex + .is_err(); self.app_scroll_positions .process_scroll_state .previous_scroll_position = 0; @@ -370,7 +499,9 @@ impl App { } pub fn get_cursor_position(&self) -> usize { - self.search_state.current_cursor_position + self.process_search_state + .search_state + .current_cursor_position } /// One of two functions allowed to run while in a dialog... @@ -394,18 +525,33 @@ impl App { self.delete_dialog_state.is_showing_dd = false; } } else if !self.is_in_dialog() { - // Pop-out mode. - self.is_expanded = true; + // Pop-out mode. We ignore if in process search. + match self.current_widget_selected { + WidgetPosition::ProcessSearch => {} + _ => self.is_expanded = true, + } } } pub fn on_backspace(&mut self) { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - if self.search_state.current_cursor_position > 0 { - self.search_state.current_cursor_position -= 1; - self.search_state + if self + .process_search_state + .search_state + .current_cursor_position + > 0 + { + self.process_search_state + .search_state + .current_cursor_position -= 1; + self.process_search_state + .search_state .current_search_query - .remove(self.search_state.current_cursor_position); + .remove( + self.process_search_state + .search_state + .current_cursor_position, + ); self.update_regex(); self.update_process_gui = true; @@ -414,7 +560,7 @@ impl App { } pub fn get_current_regex_matcher(&self) -> &std::result::Result<regex::Regex, regex::Error> { - &self.search_state.current_regex + &self.process_search_state.search_state.current_regex } pub fn on_up_key(&mut self) { @@ -438,8 +584,15 @@ impl App { pub fn on_left_key(&mut self) { if !self.is_in_dialog() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - if self.search_state.current_cursor_position > 0 { - self.search_state.current_cursor_position -= 1; + if self + .process_search_state + .search_state + .current_cursor_position + > 0 + { + self.process_search_state + .search_state + .current_cursor_position -= 1; } } } else if self.delete_dialog_state.is_showing_dd && !self.delete_dialog_state.is_on_yes { @@ -450,10 +603,19 @@ impl App { pub fn on_right_key(&mut self) { if !self.is_in_dialog() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - if self.search_state.current_cursor_position - < self.search_state.current_search_query.len() + if self + .process_search_state + .search_state + .current_cursor_position + < self + .process_search_state + .search_state + .current_search_query + .len() { - self.search_state.current_cursor_position += 1; + self.process_search_state + .search_state + .current_cursor_position += 1; } } } else if self.delete_dialog_state.is_showing_dd && self.delete_dialog_state.is_on_yes { @@ -464,7 +626,9 @@ impl App { pub fn skip_cursor_beginning(&mut self) { if !self.is_in_dialog() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state.current_cursor_position = 0; + self.process_search_state + .search_state + .current_cursor_position = 0; } } } @@ -472,12 +636,58 @@ impl App { pub fn skip_cursor_end(&mut self) { if !self.is_in_dialog() { if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state.current_cursor_position = - self.search_state.current_search_query.len(); + self.process_search_state + .search_state + .current_cursor_position = self + .process_search_state + .search_state + .current_search_query + .len(); } } } + pub fn start_dd(&mut self) { + if self + .app_scroll_positions + .process_scroll_state + .current_scroll_position + < self.canvas_data.finalized_process_data.len() as u64 + { + let current_process = if self.is_grouped() { + let group_pids = &self.canvas_data.finalized_process_data[self + .app_scroll_positions + .process_scroll_state + .current_scroll_position + as usize] + .group_pids; + + let mut ret = ("".to_string(), group_pids.clone()); + + for pid in group_pids { + if let Some(process) = self.canvas_data.process_data.get(&pid) { + ret.0 = process.name.clone(); + break; + } + } + ret + } else { + let process = self.canvas_data.finalized_process_data[self + .app_scroll_positions + .process_scroll_state + .current_scroll_position + as usize] + .clone(); + (process.name.clone(), vec![process.pid]) + }; + + self.to_delete_process_list = Some(current_process); + self.delete_dialog_state.is_showing_dd = true; + } + + self.reset_multi_tap_keys(); + } + pub fn on_char_key(&mut self, caught_char: char) { // Forbid any char key presses when showing a dialog box... if !self.is_in_dialog() { @@ -491,10 +701,18 @@ impl App { self.last_key_press = current_key_press_inst; if let WidgetPosition::ProcessSearch = self.current_widget_selected { - self.search_state + self.process_search_state + .search_state .current_search_query - .insert(self.search_state.current_cursor_position, caught_char); - self.search_state.current_cursor_position += 1; + .insert( + self.process_search_state + .search_state + .current_cursor_position, + caught_char, + ); + self.process_search_state + .search_state + .current_cursor_position += 1; self.update_regex(); @@ -502,7 +720,7 @@ impl App { } else { match caught_char { '/' => { - self.enable_searching(); + self.on_slash(); } 'd' => { if let WidgetPosition::Process = self.current_widget_selected { @@ -513,49 +731,7 @@ impl App { self.awaiting_second_char = false; self.second_char = None; - if self - .app_scroll_positions - .process_scroll_state - .current_scroll_position < self - .canvas_data - .finalized_process_data - .len() as u64 - { - let current_process = if self.is_grouped() { - let group_pids = &self - .canvas_data - .finalized_process_data[self - .app_scroll_positions - .process_scroll_state - .current_scroll_position as usize] - .group_pids; - - let mut ret = ("".to_string(), group_pids.clone()); - - for pid in group_pids { - if let Some(process) = - self.canvas_data.process_data.get(&pid) - { - ret.0 = process.name.clone(); - break; - } - } - ret - } else { - let process = self.canvas_data.finalized_process_data - [self - .app_scroll_positions - .process_scroll_state - .current_scroll_position as usize] - .clone(); - (process.name.clone(), vec![process.pid]) - }; - - self.to_delete_process_list = Some(current_process); - self.delete_dialog_state.is_showing_dd = true; - } - - self.reset_multi_tap_keys(); + self.start_dd(); } } @@ -657,6 +833,7 @@ impl App { 'L' => self.move_widget_selection_right(), 'K' => self.move_widget_selection_up(), 'J' => self.move_widget_selection_down(), + ' ' => self.on_space(), _ => {} } diff --git a/src/canvas.rs b/src/canvas.rs index 97139f54..65108285 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -23,9 +23,10 @@ use drawing_utils::*; // Headers const CPU_LEGEND_HEADER: [&str; 2] = ["CPU", "Use%"]; +const CPU_SELECT_LEGEND_HEADER: [&str; 3] = ["CPU", "Use%", "Show"]; const DISK_HEADERS: [&str; 7] = ["Disk", "Mount", "Used", "Free", "Total", "R/s", "W/s"]; const TEMP_HEADERS: [&str; 2] = ["Sensor", "Temp"]; -const MEM_HEADERS: [&str; 3] = ["Mem", "Usage", "Usage%"]; +const MEM_HEADERS: [&str; 3] = ["Mem", "Usage", "Use%"]; const NETWORK_HEADERS: [&str; 4] = ["RX", "TX", "Total RX", "Total TX"]; const FORCE_MIN_THRESHOLD: usize = 5; @@ -40,6 +41,10 @@ lazy_static! { .iter() .map(|entry| max(FORCE_MIN_THRESHOLD, entry.len())) .collect::<Vec<_>>(); + static ref CPU_SELECT_LEGEND_HEADER_LENS: Vec<usize> = CPU_SELECT_LEGEND_HEADER + .iter() + .map(|entry| max(FORCE_MIN_THRESHOLD, entry.len())) + .collect::<Vec<_>>(); static ref TEMP_HEADERS_LENS: Vec<usize> = TEMP_HEADERS .iter() .map(|entry| max(FORCE_MIN_THRESHOLD, entry.len())) @@ -99,6 +104,7 @@ impl Painter { /// This is to set some remaining styles and text. /// This bypasses some logic checks (size > 2, for example) but this /// assumes that you, the programmer, are sane and do not do stupid things. + /// RIGHT? pub fn initialize(&mut self) { self.styled_general_help_text.push(Text::Styled( GENERAL_HELP_TEXT[0].into(), @@ -532,22 +538,11 @@ impl Painter { 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(( - self.colours.cpu_colour_styles[(i) % self.colours.cpu_colour_styles.len()], - cpu.cpu_data - .iter() - .map(<(f64, f64)>::from) - .collect::<Vec<_>>(), - )); - } - - if app_state.app_config_fields.show_average_cpu { - if let Some(avg_cpu_entry) = cpu_data.first() { + for (itx, cpu) in cpu_data.iter().enumerate() { + if app_state.cpu_state.core_show_vec[itx] { cpu_entries_vec.push(( - self.colours.cpu_colour_styles[0], - avg_cpu_entry - .cpu_data + self.colours.cpu_colour_styles[(itx) % self.colours.cpu_colour_styles.len()], + cpu.cpu_data .iter() .map(<(f64, f64)>::from) .collect::<Vec<_>>(), @@ -568,7 +563,7 @@ impl Painter { ); } - let title = if app_state.is_expanded { + let title = if app_state.is_expanded && !app_state.cpu_state.is_showing_tray { const TITLE_BASE: &str = " CPU ── Esc to go back "; let repeat_num = max( 0, @@ -625,44 +620,58 @@ impl Painter { let sliced_cpu_data = &cpu_data[start_position as usize..]; let mut stringified_cpu_data: Vec<Vec<String>> = Vec::new(); - for cpu in sliced_cpu_data { + for (itx, cpu) in sliced_cpu_data.iter().enumerate() { if let Some(cpu_data) = cpu.cpu_data.last() { - stringified_cpu_data.push(vec![ + let mut entry = vec![ cpu.cpu_name.clone(), format!("{:.0}%", cpu_data.usage.round()), - ]); + ]; + + if app_state.cpu_state.is_showing_tray { + entry.push( + if app_state.cpu_state.core_show_vec[itx + start_position as usize] { + "[*]".to_string() + } else { + "[ ]".to_string() + }, + ) + } + + stringified_cpu_data.push(entry); } } - let mut cpu_row_counter: i64 = 0; - let cpu_rows = stringified_cpu_data .iter() .enumerate() + .filter(|(itx, _)| { + if app_state.cpu_state.is_showing_tray { + true + } else { + app_state.cpu_state.core_show_vec[*itx] + } + }) .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 + if itx as u64 == app_state .app_scroll_positions .cpu_scroll_state .current_scroll_position - start_position { - cpu_row_counter = -1; self.colours.currently_selected_text_style } else { - if cpu_row_counter >= 0 { - cpu_row_counter += 1; - } - self.colours.cpu_colour_styles - [itx % self.colours.cpu_colour_styles.len()] + self.colours.cpu_colour_styles[itx + + start_position as usize + % self.colours.cpu_colour_styles.len()] } } _ => { - self.colours.cpu_colour_styles - [itx % self.colours.cpu_colour_styles.len()] + self.colours.cpu_colour_styles[itx + + start_position as usize % self.colours.cpu_colour_styles.len()] } }, ) @@ -670,27 +679,70 @@ impl Painter { // 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 width_ratios = if app_state.cpu_state.is_showing_tray { + vec![0.4, 0.3, 0.3] + } else { + vec![0.5, 0.5] + }; + let variable_intrinsic_results = get_variable_intrinsic_widths( + width as u16, + &width_ratios, + if app_state.cpu_state.is_showing_tray { + &CPU_SELECT_LEGEND_HEADER_LENS + } else { + &CPU_LEGEND_HEADER_LENS + }, + ); let intrinsic_widths = &(variable_intrinsic_results.0)[0..variable_intrinsic_results.1]; + let title = if app_state.cpu_state.is_showing_tray { + const TITLE_BASE: &str = " Esc to go close "; + let repeat_num = max( + 0, + draw_loc.width as i32 - TITLE_BASE.chars().count() as i32 - 2, + ); + let result_title = format!("{} Esc to go close ", "─".repeat(repeat_num as usize)); + + result_title + } else { + "".to_string() + }; + // Draw - Table::new(CPU_LEGEND_HEADER.iter(), cpu_rows) - .block(Block::default().borders(Borders::ALL).border_style( - match app_state.current_widget_selected { + Table::new( + if app_state.cpu_state.is_showing_tray { + CPU_SELECT_LEGEND_HEADER.to_vec() + } else { + CPU_LEGEND_HEADER.to_vec() + } + .iter(), + cpu_rows, + ) + .block( + Block::default() + .title(&title) + .title_style(if app_state.is_expanded { + self.colours.highlighted_border_style + } else { + match app_state.current_widget_selected { + app::WidgetPosition::Cpu => self.colours.highlighted_border_style, + _ => self.colours.border_style, + } + }) + .borders(Borders::ALL) + .border_style(match app_state.current_widget_selected { app::WidgetPosition::Cpu => self.colours.highlighted_border_style, _ => self.colours.border_style, - }, - )) - .header_style(self.colours.table_header_style) - .widths( - &(intrinsic_widths - .iter() - .map(|calculated_width| Constraint::Length(*calculated_width as u16)) - .collect::<Vec<_>>()), - ) - .render(f, draw_loc); + }), + ) + .header_style(self.colours.table_header_style) + .widths( + &(intrinsic_widths + .iter() + .map(|calculated_width| Constraint::Length(*calculated_width as u16)) + .collect::<Vec<_>>()), + ) + .render(f, draw_loc); } fn draw_memory_graph<B: backend::Backend>( @@ -1144,7 +1196,7 @@ impl Painter { )] }; - let mut search_text = vec![if app_state.search_state.is_searching_with_pid() { + let mut search_text = vec![if app_state.process_search_state.is_searching_with_pid { Text::styled( "Search by PID (Tab for Name): ", self.colours.table_header_style, @@ -1164,21 +1216,21 @@ impl Painter { let option_row = vec![ Text::styled("Match Case (Alt+C)", self.colours.table_header_style), - if !app_state.search_state.is_ignoring_case() { + if !app_state.process_search_state.is_ignoring_case { Text::styled("[*]", self.colours.table_header_style) } else { Text::styled("[ ]", self.colours.table_header_style) }, Text::styled(" ", self.colours.table_header_style), Text::styled("Match Whole Word (Alt+W)", self.colours.table_header_style), - if app_state.search_state.is_searching_whole_word() { + if app_state.process_search_state.is_searching_whole_word { Text::styled("[*]", self.colours.table_header_style) } else { Text::styled("[ ]", self.colours.table_header_style) }, Text::styled(" ", self.colours.table_header_style), Text::styled("Use Regex (Alt+R)", self.colours.table_header_style), - if app_state.search_state.is_searching_with_regex() { + if app_state.process_search_state.is_searching_with_regex { Text::styled("[*]", self.colours.table_header_style) } else { Text::styled("[ ]", self.colours.table_header_style) diff --git a/src/canvas/canvas_colours/colour_utils.rs b/src/canvas/canvas_colours/colour_utils.rs index e54c99e9..b02e0fff 100644 --- a/src/canvas/canvas_colours/colour_utils.rs +++ b/src/canvas/canvas_colours/colour_utils.rs @@ -37,11 +37,10 @@ pub fn gen_n_styles(num_to_gen: i32) -> Vec<Style> { Style::default().fg(Color::LightMagenta), Style::default().fg(Color::LightCyan), Style::default().fg(Color::Green), - Style::default().fg(Color::Red), ]; let mut h: f32 = 0.4; // We don't need random colours... right? - for _i in 0..(num_to_gen - 6) { + for _i in 0..(num_to_gen - 5) { h = gen_hsv(h); let result = hsv_to_rgb(h, 0.5, 0.95); colour_vec.push(Style::default().fg(Color::Rgb(result.0, result.1, result.2))); diff --git a/src/main.rs b/src/main.rs index 9a321178..5c6fd2d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -254,6 +254,13 @@ fn main() -> error::Result<()> { &app.data_collection, ); + // Pre-fill CPU if needed + for itx in 0..app.canvas_data.cpu_data.len() { + if app.cpu_state.core_show_vec.len() <= itx { + app.cpu_state.core_show_vec.push(true); + } + } + // Processes let (single, grouped) = convert_process_data(&app.data_collection); app.canvas_data.process_data = single; @@ -295,8 +302,6 @@ fn handle_key_event_or_break( event: KeyEvent, app: &mut app::App, rtx: &std::sync::mpsc::Sender<ResetEvent>, ) -> bool { if event.modifiers.is_empty() { - // If only a code, and no modifiers, don't bother... - // Required catch for searching - otherwise you couldn't search with q. if event.code == KeyCode::Char('q') && !app.is_in_search_widget() { return true; @@ -314,6 +319,7 @@ fn handle_key_event_or_break( KeyCode::Enter => app.on_enter(), KeyCode::Tab => app.on_tab(), KeyCode::Backspace => app.on_backspace(), + KeyCode::Delete => app.start_dd(), _ => {} } } else { @@ -324,7 +330,7 @@ fn handle_key_event_or_break( } match event.code { - KeyCode::Char('f') => app.enable_searching(), + KeyCode::Char('f') => app.on_slash(), KeyCode::Left => app.move_widget_selection_left(), KeyCode::Right => app.move_widget_selection_right(), KeyCode::Up => app.move_widget_selection_up(), @@ -355,19 +361,19 @@ fn handle_key_event_or_break( match event.code { KeyCode::Char('c') => { if app.is_in_search_widget() { - app.search_state.toggle_ignore_case(); + app.process_search_state.toggle_ignore_case(); app.update_regex(); } } KeyCode::Char('w') => { if app.is_in_search_widget() { - app.search_state.toggle_search_whole_word(); + app.process_search_state.toggle_search_whole_word(); app.update_regex(); } } KeyCode::Char('r') => { if app.is_in_search_widget() { - app.search_state.toggle_search_regex(); + app.process_search_state.toggle_search_regex(); app.update_regex(); } } @@ -526,11 +532,11 @@ fn enable_app_case_sensitive( matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App, ) { if matches.is_present("CASE_SENSITIVE") { - app.search_state.toggle_ignore_case(); + app.process_search_state.toggle_ignore_case(); } else if let Some(flags) = &config.flags { if let Some(case_sensitive) = flags.case_sensitive { if case_sensitive { - app.search_state.toggle_ignore_case(); + app.process_search_state.toggle_ignore_case(); } } } @@ -540,11 +546,11 @@ fn enable_app_match_whole_word( matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App, ) { if matches.is_present("WHOLE_WORD") { - app.search_state.toggle_search_whole_word(); + app.process_search_state.toggle_search_whole_word(); } else if let Some(flags) = &config.flags { if let Some(whole_word) = flags.whole_word { if whole_word { - app.search_state.toggle_search_whole_word(); + app.process_search_state.toggle_search_whole_word(); } } } @@ -552,11 +558,11 @@ fn enable_app_match_whole_word( fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App) { if matches.is_present("REGEX_DEFAULT") { - app.search_state.toggle_search_regex(); + app.process_search_state.toggle_search_regex(); } else if let Some(flags) = &config.flags { if let Some(regex) = flags.regex { if regex { - app.search_state.toggle_search_regex(); + app.process_search_state.toggle_search_regex(); } } } @@ -735,7 +741,13 @@ fn update_final_process_list(app: &mut app::App) { .clone() .into_iter() |