2020-01-25 21:36:14 +00:00
|
|
|
pub mod data_harvester;
|
|
|
|
use data_harvester::{processes, temperature};
|
2019-12-16 07:21:44 +00:00
|
|
|
use std::time::Instant;
|
|
|
|
|
2020-01-29 02:24:52 +00:00
|
|
|
pub mod data_farmer;
|
|
|
|
use data_farmer::*;
|
2020-01-25 21:36:14 +00:00
|
|
|
|
2020-02-02 05:52:41 +00:00
|
|
|
use crate::{canvas, constants, utils::error::Result};
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2019-09-16 23:05:44 +00:00
|
|
|
mod process_killer;
|
|
|
|
|
2020-02-02 05:24:00 +00:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2020-02-02 04:49:44 +00:00
|
|
|
pub enum WidgetPosition {
|
2019-12-28 06:20:05 +00:00
|
|
|
Cpu,
|
|
|
|
Mem,
|
|
|
|
Disk,
|
|
|
|
Temp,
|
|
|
|
Network,
|
|
|
|
Process,
|
2020-01-12 20:41:27 +00:00
|
|
|
ProcessSearch,
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
|
2020-01-11 05:42:03 +00:00
|
|
|
#[derive(Debug)]
|
2019-09-16 20:18:42 +00:00
|
|
|
pub enum ScrollDirection {
|
2020-01-11 05:42:03 +00:00
|
|
|
// UP means scrolling up --- this usually DECREMENTS
|
2019-09-16 20:18:42 +00:00
|
|
|
UP,
|
2020-01-11 05:42:03 +00:00
|
|
|
// DOWN means scrolling down --- this usually INCREMENTS
|
2019-09-16 20:18:42 +00:00
|
|
|
DOWN,
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
lazy_static! {
|
|
|
|
static ref BASE_REGEX: std::result::Result<regex::Regex, regex::Error> =
|
|
|
|
regex::Regex::new(".*");
|
|
|
|
}
|
|
|
|
|
2020-01-25 21:36:14 +00:00
|
|
|
/// AppScrollWidgetState deals with fields for a scrollable app's current state.
|
2020-02-12 02:16:43 +00:00
|
|
|
#[derive(Default)]
|
2020-01-25 21:36:14 +00:00
|
|
|
pub struct AppScrollWidgetState {
|
2020-02-12 02:16:43 +00:00
|
|
|
pub current_scroll_position: u64,
|
|
|
|
pub previous_scroll_position: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct AppScrollState {
|
|
|
|
pub scroll_direction: ScrollDirection,
|
|
|
|
pub process_scroll_state: AppScrollWidgetState,
|
|
|
|
pub disk_scroll_state: AppScrollWidgetState,
|
|
|
|
pub temp_scroll_state: AppScrollWidgetState,
|
|
|
|
pub cpu_scroll_state: AppScrollWidgetState,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for AppScrollState {
|
|
|
|
fn default() -> Self {
|
|
|
|
AppScrollState {
|
|
|
|
scroll_direction: ScrollDirection::DOWN,
|
|
|
|
process_scroll_state: AppScrollWidgetState::default(),
|
|
|
|
disk_scroll_state: AppScrollWidgetState::default(),
|
|
|
|
temp_scroll_state: AppScrollWidgetState::default(),
|
|
|
|
cpu_scroll_state: AppScrollWidgetState::default(),
|
|
|
|
}
|
|
|
|
}
|
2020-01-25 21:36:14 +00:00
|
|
|
}
|
|
|
|
|
2020-02-03 04:15:24 +00:00
|
|
|
/// AppSearchState only deals with the search's current settings and state.
|
|
|
|
pub struct AppSearchState {
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for AppSearchState {
|
|
|
|
fn default() -> Self {
|
|
|
|
AppSearchState {
|
|
|
|
current_search_query: String::default(),
|
|
|
|
searching_pid: false,
|
2020-02-03 04:23:39 +00:00
|
|
|
ignore_case: true,
|
2020-02-03 04:15:24 +00:00
|
|
|
current_regex: BASE_REGEX.clone(),
|
|
|
|
current_cursor_position: 0,
|
|
|
|
match_word: false,
|
|
|
|
use_regex: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AppSearchState {
|
|
|
|
pub fn toggle_ignore_case(&mut self) {
|
|
|
|
self.ignore_case = !self.ignore_case;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn toggle_search_whole_word(&mut self) {
|
|
|
|
self.match_word = !self.match_word;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn toggle_search_regex(&mut self) {
|
|
|
|
self.use_regex = !self.use_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
|
|
|
|
}
|
|
|
|
}
|
2020-01-25 21:36:14 +00:00
|
|
|
|
2020-02-09 22:11:57 +00:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct AppDeleteDialogState {
|
|
|
|
pub is_showing_dd: bool,
|
|
|
|
pub is_on_yes: bool, // Defaults to "No"
|
|
|
|
}
|
|
|
|
|
2020-02-10 00:16:30 +00:00
|
|
|
pub enum AppHelpCategory {
|
|
|
|
General,
|
|
|
|
Process,
|
|
|
|
Search,
|
|
|
|
}
|
|
|
|
|
2020-02-09 22:11:57 +00:00
|
|
|
pub struct AppHelpDialogState {
|
|
|
|
pub is_showing_help: bool,
|
2020-02-10 00:16:30 +00:00
|
|
|
pub current_category: AppHelpCategory,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for AppHelpDialogState {
|
|
|
|
fn default() -> Self {
|
|
|
|
AppHelpDialogState {
|
|
|
|
is_showing_help: false,
|
|
|
|
current_category: AppHelpCategory::General,
|
|
|
|
}
|
|
|
|
}
|
2020-02-09 22:11:57 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 02:16:43 +00:00
|
|
|
/// AppConfigFields is meant to cover basic fields that would normally be set
|
|
|
|
/// by config files or launch options. Don't need to be mutable (set and forget).
|
|
|
|
pub struct AppConfigFields {
|
|
|
|
pub update_rate_in_milliseconds: u64,
|
|
|
|
pub temperature_type: temperature::TemperatureType,
|
|
|
|
pub use_dot: bool,
|
|
|
|
pub left_legend: bool,
|
|
|
|
pub show_average_cpu: bool,
|
|
|
|
pub use_current_cpu_total: bool,
|
|
|
|
}
|
|
|
|
|
2019-09-14 20:46:14 +00:00
|
|
|
pub struct App {
|
2019-12-06 05:57:04 +00:00
|
|
|
pub process_sorting_type: processes::ProcessSorting,
|
|
|
|
pub process_sorting_reverse: bool,
|
2020-01-18 00:19:20 +00:00
|
|
|
pub update_process_gui: bool,
|
2020-02-12 02:16:43 +00:00
|
|
|
pub app_scroll_positions: AppScrollState,
|
2020-02-02 04:49:44 +00:00
|
|
|
pub current_widget_selected: WidgetPosition,
|
2020-01-25 21:36:14 +00:00
|
|
|
pub data: data_harvester::Data,
|
2019-12-26 04:30:57 +00:00
|
|
|
awaiting_second_char: bool,
|
2020-02-12 02:16:43 +00:00
|
|
|
second_char: Option<char>,
|
2020-01-02 04:39:47 +00:00
|
|
|
pub dd_err: Option<String>,
|
2020-02-02 05:52:41 +00:00
|
|
|
to_delete_process_list: Option<(String, Vec<u32>)>,
|
2019-12-06 05:57:04 +00:00
|
|
|
pub is_frozen: bool,
|
2019-12-16 07:21:44 +00:00
|
|
|
last_key_press: Instant,
|
2020-02-02 04:49:44 +00:00
|
|
|
pub canvas_data: canvas::DisplayableData,
|
2020-01-08 04:39:52 +00:00
|
|
|
enable_grouping: bool,
|
2020-01-25 21:36:14 +00:00
|
|
|
enable_searching: bool,
|
|
|
|
pub data_collection: DataCollection,
|
2020-02-03 04:15:24 +00:00
|
|
|
pub search_state: AppSearchState,
|
2020-02-09 22:11:57 +00:00
|
|
|
pub delete_dialog_state: AppDeleteDialogState,
|
|
|
|
pub help_dialog_state: AppHelpDialogState,
|
2020-02-12 02:16:43 +00:00
|
|
|
pub app_config_fields: AppConfigFields,
|
|
|
|
pub is_expanded: bool,
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2019-09-14 20:46:14 +00:00
|
|
|
impl App {
|
2019-12-28 03:39:25 +00:00
|
|
|
pub fn new(
|
2020-01-08 04:40:53 +00:00
|
|
|
show_average_cpu: bool, temperature_type: temperature::TemperatureType,
|
|
|
|
update_rate_in_milliseconds: u64, use_dot: bool, left_legend: bool,
|
2020-02-14 02:06:11 +00:00
|
|
|
use_current_cpu_total: bool, current_widget_selected: WidgetPosition,
|
2019-12-28 03:39:25 +00:00
|
|
|
) -> App {
|
2019-09-09 04:09:58 +00:00
|
|
|
App {
|
2019-12-06 05:57:04 +00:00
|
|
|
process_sorting_type: processes::ProcessSorting::CPU,
|
|
|
|
process_sorting_reverse: true,
|
2020-01-18 00:19:20 +00:00
|
|
|
update_process_gui: false,
|
2020-02-14 02:06:11 +00:00
|
|
|
current_widget_selected,
|
2020-02-12 02:16:43 +00:00
|
|
|
app_scroll_positions: AppScrollState::default(),
|
2020-01-25 21:36:14 +00:00
|
|
|
data: data_harvester::Data::default(),
|
2019-12-26 04:30:57 +00:00
|
|
|
awaiting_second_char: false,
|
2020-02-12 02:16:43 +00:00
|
|
|
second_char: None,
|
2020-01-02 04:39:47 +00:00
|
|
|
dd_err: None,
|
2020-01-09 03:36:36 +00:00
|
|
|
to_delete_process_list: None,
|
2019-12-06 05:57:04 +00:00
|
|
|
is_frozen: false,
|
2019-12-16 07:21:44 +00:00
|
|
|
last_key_press: Instant::now(),
|
2020-02-02 04:49:44 +00:00
|
|
|
canvas_data: canvas::DisplayableData::default(),
|
2020-01-08 04:39:52 +00:00
|
|
|
enable_grouping: false,
|
2020-01-12 18:15:35 +00:00
|
|
|
enable_searching: false,
|
2020-01-25 21:36:14 +00:00
|
|
|
data_collection: DataCollection::default(),
|
2020-02-03 04:15:24 +00:00
|
|
|
search_state: AppSearchState::default(),
|
2020-02-09 22:11:57 +00:00
|
|
|
delete_dialog_state: AppDeleteDialogState::default(),
|
|
|
|
help_dialog_state: AppHelpDialogState::default(),
|
2020-02-12 02:16:43 +00:00
|
|
|
app_config_fields: AppConfigFields {
|
|
|
|
show_average_cpu,
|
|
|
|
temperature_type,
|
|
|
|
use_dot,
|
|
|
|
update_rate_in_milliseconds,
|
|
|
|
left_legend,
|
|
|
|
use_current_cpu_total,
|
|
|
|
},
|
|
|
|
is_expanded: false,
|
2019-09-09 04:09:58 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2019-12-16 07:21:44 +00:00
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.reset_multi_tap_keys();
|
2020-02-09 22:11:57 +00:00
|
|
|
self.help_dialog_state.is_showing_help = false;
|
|
|
|
self.delete_dialog_state.is_showing_dd = false;
|
2020-01-12 20:41:27 +00:00
|
|
|
if self.enable_searching {
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = WidgetPosition::Process;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.enable_searching = false;
|
|
|
|
}
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.current_search_query = String::new();
|
|
|
|
self.search_state.searching_pid = false;
|
2020-01-09 03:36:36 +00:00
|
|
|
self.to_delete_process_list = None;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.dd_err = None;
|
2019-12-16 07:21:44 +00:00
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn on_esc(&mut self) {
|
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
if self.is_in_dialog() {
|
2020-02-09 22:11:57 +00:00
|
|
|
self.help_dialog_state.is_showing_help = false;
|
2020-02-10 00:16:30 +00:00
|
|
|
self.help_dialog_state.current_category = AppHelpCategory::General;
|
2020-02-09 22:11:57 +00:00
|
|
|
self.delete_dialog_state.is_showing_dd = false;
|
2020-02-10 00:16:30 +00:00
|
|
|
self.delete_dialog_state.is_on_yes = false;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.to_delete_process_list = None;
|
|
|
|
self.dd_err = None;
|
|
|
|
} else if self.enable_searching {
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = WidgetPosition::Process;
|
2020-01-12 20:41:27 +00:00
|
|
|
self.enable_searching = false;
|
2020-02-12 02:16:43 +00:00
|
|
|
} else if self.is_expanded {
|
|
|
|
self.is_expanded = false;
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-16 07:21:44 +00:00
|
|
|
fn reset_multi_tap_keys(&mut self) {
|
2019-12-26 04:30:57 +00:00
|
|
|
self.awaiting_second_char = false;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.second_char = None;
|
2019-12-16 07:21:44 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
fn is_in_dialog(&self) -> bool {
|
2020-02-09 22:11:57 +00:00
|
|
|
self.help_dialog_state.is_showing_help || self.delete_dialog_state.is_showing_dd
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
|
2020-01-08 04:39:52 +00:00
|
|
|
pub fn toggle_grouping(&mut self) {
|
|
|
|
// Disallow usage whilst in a dialog and only in processes
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::Process = self.current_widget_selected {
|
2020-01-08 04:39:52 +00:00
|
|
|
self.enable_grouping = !(self.enable_grouping);
|
2020-02-02 04:49:44 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-08 04:39:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 03:54:14 +00:00
|
|
|
pub fn on_tab(&mut self) {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process => self.toggle_grouping(),
|
|
|
|
WidgetPosition::Disk => {}
|
2020-02-03 04:15:24 +00:00
|
|
|
WidgetPosition::ProcessSearch => {
|
|
|
|
if self.search_state.is_searching_with_pid() {
|
|
|
|
self.search_with_name();
|
|
|
|
} else {
|
|
|
|
self.search_with_pid();
|
|
|
|
}
|
|
|
|
}
|
2020-01-09 03:54:14 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 04:39:52 +00:00
|
|
|
pub fn is_grouped(&self) -> bool {
|
|
|
|
self.enable_grouping
|
|
|
|
}
|
|
|
|
|
2020-01-29 02:24:52 +00:00
|
|
|
pub fn enable_searching(&mut self) {
|
2020-01-12 18:15:35 +00:00
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process | WidgetPosition::ProcessSearch => {
|
2020-01-29 02:24:52 +00:00
|
|
|
// Toggle on
|
|
|
|
self.enable_searching = true;
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = WidgetPosition::ProcessSearch;
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
_ => {}
|
2020-01-12 18:15:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_searching(&self) -> bool {
|
|
|
|
self.enable_searching
|
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn is_in_search_widget(&self) -> bool {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-01-12 20:41:27 +00:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn search_with_pid(&mut self) {
|
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.searching_pid = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn search_with_name(&mut self) {
|
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.searching_pid = false;
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
pub fn get_current_search_query(&self) -> &String {
|
2020-02-03 04:15:24 +00:00
|
|
|
&self.search_state.current_search_query
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
|
2020-02-02 05:24:00 +00:00
|
|
|
pub fn toggle_ignore_case(&mut self) {
|
2020-01-16 03:57:00 +00:00
|
|
|
if !self.is_in_dialog() && self.is_searching() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.toggle_ignore_case();
|
2020-02-02 05:24:00 +00:00
|
|
|
self.update_regex();
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-16 03:57:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 04:15:24 +00:00
|
|
|
pub fn update_regex(&mut self) {
|
|
|
|
self.search_state.current_regex = if self.search_state.current_search_query.is_empty() {
|
2020-02-02 05:24:00 +00:00
|
|
|
BASE_REGEX.clone()
|
|
|
|
} else {
|
2020-02-03 04:15:24 +00:00
|
|
|
let mut final_regex_string = self.search_state.current_search_query.clone();
|
|
|
|
|
|
|
|
if !self.search_state.is_searching_with_regex() {
|
|
|
|
final_regex_string = regex::escape(&final_regex_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.search_state.is_searching_whole_word() {
|
|
|
|
final_regex_string = format!("^{}$", final_regex_string);
|
|
|
|
}
|
|
|
|
if self.search_state.is_ignoring_case() {
|
|
|
|
final_regex_string = format!("(?i){}", final_regex_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
regex::Regex::new(&final_regex_string)
|
2020-02-02 05:24:00 +00:00
|
|
|
};
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.previous_scroll_position = 0;
|
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0;
|
2020-02-02 05:24:00 +00:00
|
|
|
}
|
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn get_cursor_position(&self) -> usize {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.current_cursor_position
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
/// One of two functions allowed to run while in a dialog...
|
|
|
|
pub fn on_enter(&mut self) {
|
2020-02-12 02:16:43 +00:00
|
|
|
if self.delete_dialog_state.is_showing_dd {
|
|
|
|
if self.delete_dialog_state.is_on_yes {
|
|
|
|
// If within dd...
|
|
|
|
if self.dd_err.is_none() {
|
|
|
|
// Also ensure that we didn't just fail a dd...
|
|
|
|
let dd_result = self.kill_highlighted_process();
|
|
|
|
self.delete_dialog_state.is_on_yes = false;
|
|
|
|
|
|
|
|
// Check if there was an issue... if so, inform the user.
|
|
|
|
if let Err(dd_err) = dd_result {
|
|
|
|
self.dd_err = Some(dd_err.to_string());
|
|
|
|
} else {
|
|
|
|
self.delete_dialog_state.is_showing_dd = false;
|
|
|
|
}
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
} else {
|
|
|
|
self.delete_dialog_state.is_showing_dd = false;
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
} else if !self.is_in_dialog() {
|
|
|
|
// Pop-out mode.
|
|
|
|
self.is_expanded = true;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 20:41:27 +00:00
|
|
|
pub fn on_backspace(&mut self) {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
if self.search_state.current_cursor_position > 0 {
|
|
|
|
self.search_state.current_cursor_position -= 1;
|
|
|
|
self.search_state
|
|
|
|
.current_search_query
|
|
|
|
.remove(self.search_state.current_cursor_position);
|
2020-01-17 02:33:06 +00:00
|
|
|
|
2020-02-02 05:24:00 +00:00
|
|
|
self.update_regex();
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 23:45:11 +00:00
|
|
|
pub fn get_current_regex_matcher(&self) -> &std::result::Result<regex::Regex, regex::Error> {
|
2020-02-03 04:15:24 +00:00
|
|
|
&self.search_state.current_regex
|
2020-01-12 23:45:11 +00:00
|
|
|
}
|
|
|
|
|
2020-01-17 02:33:06 +00:00
|
|
|
pub fn on_up_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-01-17 02:33:06 +00:00
|
|
|
} else {
|
|
|
|
self.decrement_position_count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_down_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-01-17 02:33:06 +00:00
|
|
|
} else {
|
|
|
|
self.increment_position_count();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_left_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
if self.search_state.current_cursor_position > 0 {
|
|
|
|
self.search_state.current_cursor_position -= 1;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-10 05:16:11 +00:00
|
|
|
} else if self.delete_dialog_state.is_showing_dd && !self.delete_dialog_state.is_on_yes {
|
|
|
|
self.delete_dialog_state.is_on_yes = true;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_right_key(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
if self.search_state.current_cursor_position
|
|
|
|
< self.search_state.current_search_query.len()
|
|
|
|
{
|
|
|
|
self.search_state.current_cursor_position += 1;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-10 05:16:11 +00:00
|
|
|
} else if self.delete_dialog_state.is_showing_dd && self.delete_dialog_state.is_on_yes {
|
|
|
|
self.delete_dialog_state.is_on_yes = false;
|
2020-01-17 02:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-18 00:53:42 +00:00
|
|
|
pub fn skip_cursor_beginning(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.current_cursor_position = 0;
|
2020-01-18 00:53:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_cursor_end(&mut self) {
|
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state.current_cursor_position =
|
|
|
|
self.search_state.current_search_query.len();
|
2020-01-18 00:53:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
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() {
|
2019-12-16 07:21:44 +00:00
|
|
|
let current_key_press_inst = Instant::now();
|
2020-01-08 04:40:53 +00:00
|
|
|
if current_key_press_inst
|
|
|
|
.duration_since(self.last_key_press)
|
|
|
|
.as_millis() > constants::MAX_KEY_TIMEOUT_IN_MILLISECONDS
|
|
|
|
{
|
2019-12-16 07:21:44 +00:00
|
|
|
self.reset_multi_tap_keys();
|
|
|
|
}
|
|
|
|
self.last_key_press = current_key_press_inst;
|
|
|
|
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
|
2020-02-03 04:15:24 +00:00
|
|
|
self.search_state
|
|
|
|
.current_search_query
|
|
|
|
.insert(self.search_state.current_cursor_position, caught_char);
|
|
|
|
self.search_state.current_cursor_position += 1;
|
2020-01-16 03:57:00 +00:00
|
|
|
|
2020-02-02 05:24:00 +00:00
|
|
|
self.update_regex();
|
|
|
|
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-01-12 20:41:27 +00:00
|
|
|
} else {
|
|
|
|
match caught_char {
|
|
|
|
'/' => {
|
2020-01-29 02:24:52 +00:00
|
|
|
self.enable_searching();
|
2020-01-12 18:15:35 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'd' => {
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::Process = self.current_widget_selected {
|
2020-02-12 02:16:43 +00:00
|
|
|
let mut is_first_d = true;
|
|
|
|
if let Some(second_char) = self.second_char {
|
|
|
|
if self.awaiting_second_char && second_char == 'd' {
|
|
|
|
is_first_d = false;
|
|
|
|
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;
|
|
|
|
}
|
2020-02-02 05:52:41 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
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();
|
2020-02-02 05:52:41 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
}
|
2020-02-02 04:49:44 +00:00
|
|
|
|
2020-02-12 02:16:43 +00:00
|
|
|
if is_first_d {
|
2020-01-12 20:41:27 +00:00
|
|
|
self.awaiting_second_char = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.second_char = Some('d');
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
'g' => {
|
2020-02-12 02:16:43 +00:00
|
|
|
let mut is_first_g = true;
|
|
|
|
if let Some(second_char) = self.second_char {
|
|
|
|
if self.awaiting_second_char && second_char == 'g' {
|
|
|
|
is_first_g = false;
|
|
|
|
self.awaiting_second_char = false;
|
|
|
|
self.second_char = None;
|
|
|
|
self.skip_to_first();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if is_first_g {
|
2020-01-01 23:39:59 +00:00
|
|
|
self.awaiting_second_char = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.second_char = Some('g');
|
2020-01-01 23:39:59 +00:00
|
|
|
}
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'G' => self.skip_to_last(),
|
|
|
|
'k' => self.decrement_position_count(),
|
|
|
|
'j' => self.increment_position_count(),
|
|
|
|
'f' => {
|
|
|
|
self.is_frozen = !self.is_frozen;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'c' => {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::CPU => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::CPU;
|
|
|
|
self.process_sorting_reverse = true;
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'm' => {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::MEM => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::MEM;
|
|
|
|
self.process_sorting_reverse = true;
|
|
|
|
}
|
2020-01-08 04:40:53 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0;
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
'p' => {
|
|
|
|
// Disable if grouping
|
|
|
|
if !self.enable_grouping {
|
|
|
|
match self.process_sorting_type {
|
|
|
|
processes::ProcessSorting::PID => {
|
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.process_sorting_type = processes::ProcessSorting::PID;
|
|
|
|
self.process_sorting_reverse = false;
|
|
|
|
}
|
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0;
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'n' => {
|
2020-01-08 04:39:52 +00:00
|
|
|
match self.process_sorting_type {
|
2020-01-12 20:41:27 +00:00
|
|
|
processes::ProcessSorting::NAME => {
|
2020-01-08 04:40:53 +00:00
|
|
|
self.process_sorting_reverse = !self.process_sorting_reverse
|
|
|
|
}
|
2020-01-08 04:39:52 +00:00
|
|
|
_ => {
|
2020-01-12 20:41:27 +00:00
|
|
|
self.process_sorting_type = processes::ProcessSorting::NAME;
|
2020-01-08 04:39:52 +00:00
|
|
|
self.process_sorting_reverse = false;
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
2020-01-18 00:19:20 +00:00
|
|
|
self.update_process_gui = true;
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
'?' => {
|
2020-02-09 22:11:57 +00:00
|
|
|
self.help_dialog_state.is_showing_help = true;
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-01-12 20:41:27 +00:00
|
|
|
_ => {}
|
2019-09-10 22:22:34 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
|
|
|
|
if let Some(second_char) = self.second_char {
|
|
|
|
if self.awaiting_second_char && caught_char != second_char {
|
|
|
|
self.awaiting_second_char = false;
|
|
|
|
}
|
2019-10-10 02:00:10 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-10 05:16:11 +00:00
|
|
|
} else if self.help_dialog_state.is_showing_help {
|
|
|
|
match caught_char {
|
|
|
|
'1' => self.help_dialog_state.current_category = AppHelpCategory::General,
|
|
|
|
'2' => self.help_dialog_state.current_category = AppHelpCategory::Process,
|
|
|
|
'3' => self.help_dialog_state.current_category = AppHelpCategory::Search,
|
|
|
|
_ => {}
|
2020-02-10 00:16:30 +00:00
|
|
|
}
|
2019-09-17 01:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 04:39:47 +00:00
|
|
|
pub fn kill_highlighted_process(&mut self) -> Result<()> {
|
|
|
|
// Technically unnecessary but this is a good check...
|
2020-02-02 04:49:44 +00:00
|
|
|
if let WidgetPosition::Process = self.current_widget_selected {
|
2020-01-09 03:36:36 +00:00
|
|
|
if let Some(current_selected_processes) = &(self.to_delete_process_list) {
|
2020-02-02 05:52:41 +00:00
|
|
|
for pid in ¤t_selected_processes.1 {
|
|
|
|
process_killer::kill_process_given_pid(*pid)?;
|
2020-01-09 03:36:36 +00:00
|
|
|
}
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-01-09 03:36:36 +00:00
|
|
|
self.to_delete_process_list = None;
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2019-09-17 01:45:48 +00:00
|
|
|
Ok(())
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
|
|
|
|
2020-02-02 05:52:41 +00:00
|
|
|
pub fn get_to_delete_processes(&self) -> Option<(String, Vec<u32>)> {
|
2020-01-09 03:36:36 +00:00
|
|
|
self.to_delete_process_list.clone()
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
|
|
|
|
2019-09-17 02:39:57 +00:00
|
|
|
// For now, these are hard coded --- in the future, they shouldn't be!
|
|
|
|
//
|
|
|
|
// General idea for now:
|
|
|
|
// CPU -(down)> MEM
|
|
|
|
// MEM -(down)> Network, -(right)> TEMP
|
|
|
|
// TEMP -(down)> Disk, -(left)> MEM, -(up)> CPU
|
2020-02-03 04:36:44 +00:00
|
|
|
// Disk -(down)> Processes, -(left)> MEM, -(up)> TEMP
|
2019-09-17 02:39:57 +00:00
|
|
|
// Network -(up)> MEM, -(right)> PROC
|
2020-02-03 04:36:44 +00:00
|
|
|
// PROC -(up)> Disk, -(down)> PROC_SEARCH, -(left)> Network
|
|
|
|
// PROC_SEARCH -(up)> PROC, -(left)> Network
|
2020-02-12 02:16:43 +00:00
|
|
|
pub fn move_widget_selection_left(&mut self) {
|
|
|
|
if !self.is_in_dialog() && !self.is_expanded {
|
2020-02-02 04:49:44 +00:00
|
|
|
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,
|
2020-01-02 04:39:47 +00:00
|
|
|
};
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2020-02-12 02:16:43 +00:00
|
|
|
pub fn move_widget_selection_right(&mut self) {
|
|
|
|
if !self.is_in_dialog() && !self.is_expanded {
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = match self.current_widget_selected {
|
|
|
|
WidgetPosition::Mem => WidgetPosition::Temp,
|
|
|
|
WidgetPosition::Network => WidgetPosition::Process,
|
|
|
|
_ => self.current_widget_selected,
|
2020-01-02 04:39:47 +00:00
|
|
|
};
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 02:16:43 +00:00
|
|
|
pub fn move_widget_selection_up(&mut self) {
|
|
|
|
if !self.is_in_dialog() && !self.is_expanded {
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = match self.current_widget_selected {
|
|
|
|
WidgetPosition::Mem => WidgetPosition::Cpu,
|
|
|
|
WidgetPosition::Network => WidgetPosition::Mem,
|
2020-02-03 04:36:44 +00:00
|
|
|
WidgetPosition::Process => WidgetPosition::Disk,
|
|
|
|
WidgetPosition::ProcessSearch => WidgetPosition::Process,
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::Temp => WidgetPosition::Cpu,
|
|
|
|
WidgetPosition::Disk => WidgetPosition::Temp,
|
|
|
|
_ => self.current_widget_selected,
|
2020-01-02 04:39:47 +00:00
|
|
|
};
|
2020-02-12 02:16:43 +00:00
|
|
|
} else if self.is_expanded {
|
|
|
|
self.current_widget_selected = match self.current_widget_selected {
|
|
|
|
WidgetPosition::ProcessSearch => WidgetPosition::Process,
|
|
|
|
_ => self.current_widget_selected,
|
|
|
|
};
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
|
|
|
|
self.reset_multi_tap_keys();
|
2019-09-09 22:34:13 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
|
2020-02-12 02:16:43 +00:00
|
|
|
pub fn move_widget_selection_down(&mut self) {
|
|
|
|
if !self.is_in_dialog() && !self.is_expanded {
|
2020-02-02 04:49:44 +00:00
|
|
|
self.current_widget_selected = match self.current_widget_selected {
|
|
|
|
WidgetPosition::Cpu => WidgetPosition::Mem,
|
|
|
|
WidgetPosition::Mem => WidgetPosition::Network,
|
|
|
|
WidgetPosition::Temp => WidgetPosition::Disk,
|
2020-02-03 04:36:44 +00:00
|
|
|
WidgetPosition::Disk => WidgetPosition::Process,
|
|
|
|
WidgetPosition::Process => {
|
2020-01-12 20:41:27 +00:00
|
|
|
if self.is_searching() {
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::ProcessSearch
|
2020-01-12 20:41:27 +00:00
|
|
|
} else {
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::Process
|
2020-01-12 20:41:27 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-02 04:49:44 +00:00
|
|
|
_ => self.current_widget_selected,
|
2020-01-02 04:39:47 +00:00
|
|
|
};
|
2020-02-12 02:16:43 +00:00
|
|
|
} else if self.is_expanded {
|
|
|
|
self.current_widget_selected = match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process => {
|
|
|
|
if self.is_searching() {
|
|
|
|
WidgetPosition::ProcessSearch
|
|
|
|
} else {
|
|
|
|
WidgetPosition::Process
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => self.current_widget_selected,
|
|
|
|
};
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
|
|
|
|
self.reset_multi_tap_keys();
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_first(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
2020-02-12 02:16:43 +00:00
|
|
|
WidgetPosition::Process => {
|
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = 0
|
|
|
|
}
|
|
|
|
WidgetPosition::Temp => {
|
|
|
|
self.app_scroll_positions
|
|
|
|
.temp_scroll_state
|
|
|
|
.current_scroll_position = 0
|
|
|
|
}
|
|
|
|
WidgetPosition::Disk => {
|
|
|
|
self.app_scroll_positions
|
|
|
|
.disk_scroll_state
|
|
|
|
.current_scroll_position = 0
|
|
|
|
}
|
|
|
|
WidgetPosition::Cpu => {
|
|
|
|
self.app_scroll_positions
|
|
|
|
.cpu_scroll_state
|
|
|
|
.current_scroll_position = 0
|
|
|
|
}
|
2020-01-02 04:39:47 +00:00
|
|
|
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions.scroll_direction = ScrollDirection::UP;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.reset_multi_tap_keys();
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn skip_to_last(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process => {
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = self.canvas_data.finalized_process_data.len() as u64 - 1
|
2020-01-08 04:40:53 +00:00
|
|
|
}
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::Temp => {
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.temp_scroll_state
|
|
|
|
.current_scroll_position = self.canvas_data.temp_sensor_data.len() as u64 - 1
|
2020-01-08 04:40:53 +00:00
|
|
|
}
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::Disk => {
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.disk_scroll_state
|
|
|
|
.current_scroll_position = self.canvas_data.disk_data.len() as u64 - 1
|
2020-01-08 04:40:53 +00:00
|
|
|
}
|
2020-02-02 04:49:44 +00:00
|
|
|
WidgetPosition::Cpu => {
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.cpu_scroll_state
|
|
|
|
.current_scroll_position = self.canvas_data.cpu_data.len() as u64 - 1;
|
2020-01-02 04:39:47 +00:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions.scroll_direction = ScrollDirection::DOWN;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.reset_multi_tap_keys();
|
2019-12-26 04:30:57 +00:00
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|
2019-09-15 18:16:18 +00:00
|
|
|
|
|
|
|
pub fn decrement_position_count(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process => self.change_process_position(-1),
|
|
|
|
WidgetPosition::Temp => self.change_temp_position(-1),
|
|
|
|
WidgetPosition::Disk => self.change_disk_position(-1),
|
2020-02-08 19:28:19 +00:00
|
|
|
WidgetPosition::Cpu => self.change_cpu_table_position(-1), // TODO: [PO?] Temporary, may change if we add scaling
|
2020-01-02 04:39:47 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions.scroll_direction = ScrollDirection::UP;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn increment_position_count(&mut self) {
|
2020-01-02 04:39:47 +00:00
|
|
|
if !self.is_in_dialog() {
|
2020-02-02 04:49:44 +00:00
|
|
|
match self.current_widget_selected {
|
|
|
|
WidgetPosition::Process => self.change_process_position(1),
|
|
|
|
WidgetPosition::Temp => self.change_temp_position(1),
|
|
|
|
WidgetPosition::Disk => self.change_disk_position(1),
|
2020-02-08 19:28:19 +00:00
|
|
|
WidgetPosition::Cpu => self.change_cpu_table_position(1), // TODO: [PO?] Temporary, may change if we add scaling
|
2020-01-02 04:39:47 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions.scroll_direction = ScrollDirection::DOWN;
|
2020-01-02 04:39:47 +00:00
|
|
|
self.reset_multi_tap_keys();
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-01 22:55:15 +00:00
|
|
|
fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
|
2020-02-12 02:16:43 +00:00
|
|
|
let current_posn = self
|
|
|
|
.app_scroll_positions
|
|
|
|
.cpu_scroll_state
|
|
|
|
.current_scroll_position;
|
|
|
|
|
|
|
|
if current_posn as i64 + num_to_change_by >= 0
|
|
|
|
&& current_posn as i64 + num_to_change_by < self.canvas_data.cpu_data.len() as i64
|
2020-01-27 01:14:14 +00:00
|
|
|
{
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.cpu_scroll_state
|
|
|
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
2020-01-01 22:55:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_process_position(&mut self, num_to_change_by: i64) {
|
2020-02-12 02:16:43 +00:00
|
|
|
let current_posn = self
|
|
|
|
.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position;
|
|
|
|
|
|
|
|
if current_posn as i64 + num_to_change_by >= 0
|
|
|
|
&& current_posn as i64 + num_to_change_by
|
2020-02-02 05:24:00 +00:00
|
|
|
< self.canvas_data.finalized_process_data.len() as i64
|
2019-09-16 20:18:42 +00:00
|
|
|
{
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.process_scroll_state
|
|
|
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
2020-02-12 02:16:43 +00:00
|
|
|
let current_posn = self
|
|
|
|
.app_scroll_positions
|
|
|
|
.temp_scroll_state
|
|
|
|
.current_scroll_position;
|
|
|
|
|
|
|
|
if current_posn as i64 + num_to_change_by >= 0
|
|
|
|
&& current_posn as i64 + num_to_change_by
|
2020-02-02 05:24:00 +00:00
|
|
|
< self.canvas_data.temp_sensor_data.len() as i64
|
2019-09-25 20:43:13 +00:00
|
|
|
{
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.temp_scroll_state
|
|
|
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 05:57:04 +00:00
|
|
|
fn change_disk_position(&mut self, num_to_change_by: i64) {
|
2020-02-12 02:16:43 +00:00
|
|
|
let current_posn = self
|
|
|
|
.app_scroll_positions
|
|
|
|
.disk_scroll_state
|
|
|
|
.current_scroll_position;
|
|
|
|
|
|
|
|
if current_posn as i64 + num_to_change_by >= 0
|
|
|
|
&& current_posn as i64 + num_to_change_by < self.canvas_data.disk_data.len() as i64
|
2019-09-25 20:43:13 +00:00
|
|
|
{
|
2020-02-12 02:16:43 +00:00
|
|
|
self.app_scroll_positions
|
|
|
|
.disk_scroll_state
|
|
|
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
2019-09-15 18:16:18 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 23:56:23 +00:00
|
|
|
}
|