mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-26 23:24:20 +02:00
Added maximizing mode to allow users to zoom into a particular widget. Not 100% done.
This commit is contained in:
parent
908960f783
commit
f0dad8f5bf
@ -22,6 +22,10 @@ Features of bottom include:
|
|||||||
|
|
||||||
- Temperature widget to monitor detected sensors in your system.
|
- Temperature widget to monitor detected sensors in your system.
|
||||||
|
|
||||||
|
- Config file support for custom colours and default options.
|
||||||
|
|
||||||
|
- Maximizing of widgets of interest.
|
||||||
|
|
||||||
The compatibility of each widget and operating systems are, as of version 0.1.0, as follows:
|
The compatibility of each widget and operating systems are, as of version 0.1.0, as follows:
|
||||||
|
|
||||||
| OS | CPU | Memory | Disks | Temperature | Processes | Networks |
|
| OS | CPU | Memory | Disks | Temperature | Processes | Networks |
|
||||||
@ -137,10 +141,12 @@ Run using `btm`.
|
|||||||
|
|
||||||
- `Ctrl/Shift-Arrow` or `H/J/K/L` to navigate between widgets. **Note that on macOS, `Ctrl`-arrow keys conflicts with an existing macOS binding, use `Shift`-arrow key instead.**
|
- `Ctrl/Shift-Arrow` or `H/J/K/L` to navigate between widgets. **Note that on macOS, `Ctrl`-arrow keys conflicts with an existing macOS binding, use `Shift`-arrow key instead.**
|
||||||
|
|
||||||
- `Esc` to close a dialog window.
|
- `Esc` to close a dialog window or exit maximized mode.
|
||||||
|
|
||||||
- `?` to get a help screen explaining the controls. Note all controls except `Esc` to close the dialog will be disabled while this is open.
|
- `?` to get a help screen explaining the controls. Note all controls except `Esc` to close the dialog will be disabled while this is open.
|
||||||
|
|
||||||
|
- `Enter` on a widget to maximize the widget.
|
||||||
|
|
||||||
#### Scrollable Tables
|
#### Scrollable Tables
|
||||||
|
|
||||||
- `Up` or `k` and `Down` or `j` scrolls through the list if the widget is a table (Temperature, Disks, Processes).
|
- `Up` or `k` and `Down` or `j` scrolls through the list if the widget is a table (Temperature, Disks, Processes).
|
||||||
|
343
src/app.rs
343
src/app.rs
@ -33,17 +33,31 @@ lazy_static! {
|
|||||||
regex::Regex::new(".*");
|
regex::Regex::new(".*");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AppConfigFields is meant to cover basic fields that would normally be set
|
/// AppScrollWidgetState deals with fields for a scrollable app's current state.
|
||||||
/// by config files or launch options. Don't need to be mutable (set and forget).
|
#[derive(Default)]
|
||||||
pub struct AppConfigFields {
|
pub struct AppScrollWidgetState {
|
||||||
pub update_rate_in_milliseconds: u64,
|
pub current_scroll_position: u64,
|
||||||
pub temperature_type: temperature::TemperatureType,
|
pub previous_scroll_position: u64,
|
||||||
pub use_dot: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AppScrollWidgetState deals with fields for a scrollable app's current state.
|
pub struct AppScrollState {
|
||||||
pub struct AppScrollWidgetState {
|
pub scroll_direction: ScrollDirection,
|
||||||
pub widget_scroll_position: i64,
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AppSearchState only deals with the search's current settings and state.
|
/// AppSearchState only deals with the search's current settings and state.
|
||||||
@ -131,35 +145,29 @@ impl Default for AppHelpDialogState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: [OPT] Group like fields together... this is kinda gross to step through
|
/// 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,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
// Sorting
|
|
||||||
pub process_sorting_type: processes::ProcessSorting,
|
pub process_sorting_type: processes::ProcessSorting,
|
||||||
pub process_sorting_reverse: bool,
|
pub process_sorting_reverse: bool,
|
||||||
pub update_process_gui: bool,
|
pub update_process_gui: bool,
|
||||||
// Positioning
|
pub app_scroll_positions: AppScrollState,
|
||||||
pub scroll_direction: ScrollDirection,
|
|
||||||
pub currently_selected_process_position: u64,
|
|
||||||
pub currently_selected_disk_position: u64,
|
|
||||||
pub currently_selected_temperature_position: u64,
|
|
||||||
pub currently_selected_cpu_table_position: u64,
|
|
||||||
pub previous_disk_position: u64,
|
|
||||||
pub previous_temp_position: u64,
|
|
||||||
pub previous_process_position: u64,
|
|
||||||
pub previous_cpu_table_position: u64,
|
|
||||||
pub temperature_type: temperature::TemperatureType,
|
|
||||||
pub update_rate_in_milliseconds: u64,
|
|
||||||
pub show_average_cpu: bool,
|
|
||||||
pub current_widget_selected: WidgetPosition,
|
pub current_widget_selected: WidgetPosition,
|
||||||
pub data: data_harvester::Data,
|
pub data: data_harvester::Data,
|
||||||
awaiting_second_char: bool,
|
awaiting_second_char: bool,
|
||||||
second_char: char,
|
second_char: Option<char>,
|
||||||
pub use_dot: bool,
|
|
||||||
pub dd_err: Option<String>,
|
pub dd_err: Option<String>,
|
||||||
to_delete_process_list: Option<(String, Vec<u32>)>,
|
to_delete_process_list: Option<(String, Vec<u32>)>,
|
||||||
pub is_frozen: bool,
|
pub is_frozen: bool,
|
||||||
pub left_legend: bool,
|
|
||||||
pub use_current_cpu_total: bool,
|
|
||||||
last_key_press: Instant,
|
last_key_press: Instant,
|
||||||
pub canvas_data: canvas::DisplayableData,
|
pub canvas_data: canvas::DisplayableData,
|
||||||
enable_grouping: bool,
|
enable_grouping: bool,
|
||||||
@ -168,6 +176,8 @@ pub struct App {
|
|||||||
pub search_state: AppSearchState,
|
pub search_state: AppSearchState,
|
||||||
pub delete_dialog_state: AppDeleteDialogState,
|
pub delete_dialog_state: AppDeleteDialogState,
|
||||||
pub help_dialog_state: AppHelpDialogState,
|
pub help_dialog_state: AppHelpDialogState,
|
||||||
|
pub app_config_fields: AppConfigFields,
|
||||||
|
pub is_expanded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
@ -180,28 +190,14 @@ impl App {
|
|||||||
process_sorting_type: processes::ProcessSorting::CPU,
|
process_sorting_type: processes::ProcessSorting::CPU,
|
||||||
process_sorting_reverse: true,
|
process_sorting_reverse: true,
|
||||||
update_process_gui: false,
|
update_process_gui: false,
|
||||||
temperature_type,
|
|
||||||
update_rate_in_milliseconds,
|
|
||||||
show_average_cpu,
|
|
||||||
current_widget_selected: WidgetPosition::Process,
|
current_widget_selected: WidgetPosition::Process,
|
||||||
scroll_direction: ScrollDirection::DOWN,
|
app_scroll_positions: AppScrollState::default(),
|
||||||
currently_selected_process_position: 0,
|
|
||||||
currently_selected_disk_position: 0,
|
|
||||||
currently_selected_temperature_position: 0,
|
|
||||||
currently_selected_cpu_table_position: 0,
|
|
||||||
previous_process_position: 0,
|
|
||||||
previous_disk_position: 0,
|
|
||||||
previous_temp_position: 0,
|
|
||||||
previous_cpu_table_position: 0,
|
|
||||||
data: data_harvester::Data::default(),
|
data: data_harvester::Data::default(),
|
||||||
awaiting_second_char: false,
|
awaiting_second_char: false,
|
||||||
second_char: ' ',
|
second_char: None,
|
||||||
use_dot,
|
|
||||||
dd_err: None,
|
dd_err: None,
|
||||||
to_delete_process_list: None,
|
to_delete_process_list: None,
|
||||||
is_frozen: false,
|
is_frozen: false,
|
||||||
left_legend,
|
|
||||||
use_current_cpu_total,
|
|
||||||
last_key_press: Instant::now(),
|
last_key_press: Instant::now(),
|
||||||
canvas_data: canvas::DisplayableData::default(),
|
canvas_data: canvas::DisplayableData::default(),
|
||||||
enable_grouping: false,
|
enable_grouping: false,
|
||||||
@ -210,6 +206,15 @@ impl App {
|
|||||||
search_state: AppSearchState::default(),
|
search_state: AppSearchState::default(),
|
||||||
delete_dialog_state: AppDeleteDialogState::default(),
|
delete_dialog_state: AppDeleteDialogState::default(),
|
||||||
help_dialog_state: AppHelpDialogState::default(),
|
help_dialog_state: AppHelpDialogState::default(),
|
||||||
|
app_config_fields: AppConfigFields {
|
||||||
|
show_average_cpu,
|
||||||
|
temperature_type,
|
||||||
|
use_dot,
|
||||||
|
update_rate_in_milliseconds,
|
||||||
|
left_legend,
|
||||||
|
use_current_cpu_total,
|
||||||
|
},
|
||||||
|
is_expanded: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,12 +244,14 @@ impl App {
|
|||||||
} else if self.enable_searching {
|
} else if self.enable_searching {
|
||||||
self.current_widget_selected = WidgetPosition::Process;
|
self.current_widget_selected = WidgetPosition::Process;
|
||||||
self.enable_searching = false;
|
self.enable_searching = false;
|
||||||
|
} else if self.is_expanded {
|
||||||
|
self.is_expanded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_multi_tap_keys(&mut self) {
|
fn reset_multi_tap_keys(&mut self) {
|
||||||
self.awaiting_second_char = false;
|
self.awaiting_second_char = false;
|
||||||
self.second_char = ' ';
|
self.second_char = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_in_dialog(&self) -> bool {
|
fn is_in_dialog(&self) -> bool {
|
||||||
@ -354,8 +361,12 @@ impl App {
|
|||||||
|
|
||||||
regex::Regex::new(&final_regex_string)
|
regex::Regex::new(&final_regex_string)
|
||||||
};
|
};
|
||||||
self.previous_process_position = 0;
|
self.app_scroll_positions
|
||||||
self.currently_selected_process_position = 0;
|
.process_scroll_state
|
||||||
|
.previous_scroll_position = 0;
|
||||||
|
self.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cursor_position(&self) -> usize {
|
pub fn get_cursor_position(&self) -> usize {
|
||||||
@ -364,7 +375,8 @@ impl App {
|
|||||||
|
|
||||||
/// One of two functions allowed to run while in a dialog...
|
/// One of two functions allowed to run while in a dialog...
|
||||||
pub fn on_enter(&mut self) {
|
pub fn on_enter(&mut self) {
|
||||||
if self.delete_dialog_state.is_showing_dd && self.delete_dialog_state.is_on_yes {
|
if self.delete_dialog_state.is_showing_dd {
|
||||||
|
if self.delete_dialog_state.is_on_yes {
|
||||||
// If within dd...
|
// If within dd...
|
||||||
if self.dd_err.is_none() {
|
if self.dd_err.is_none() {
|
||||||
// Also ensure that we didn't just fail a dd...
|
// Also ensure that we didn't just fail a dd...
|
||||||
@ -381,6 +393,10 @@ impl App {
|
|||||||
} else {
|
} else {
|
||||||
self.delete_dialog_state.is_showing_dd = false;
|
self.delete_dialog_state.is_showing_dd = false;
|
||||||
}
|
}
|
||||||
|
} else if !self.is_in_dialog() {
|
||||||
|
// Pop-out mode.
|
||||||
|
self.is_expanded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_backspace(&mut self) {
|
pub fn on_backspace(&mut self) {
|
||||||
@ -490,16 +506,28 @@ impl App {
|
|||||||
}
|
}
|
||||||
'd' => {
|
'd' => {
|
||||||
if let WidgetPosition::Process = self.current_widget_selected {
|
if let WidgetPosition::Process = self.current_widget_selected {
|
||||||
if self.awaiting_second_char && self.second_char == 'd' {
|
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.awaiting_second_char = false;
|
||||||
self.second_char = ' ';
|
self.second_char = None;
|
||||||
|
|
||||||
if self.currently_selected_process_position
|
if self
|
||||||
< self.canvas_data.finalized_process_data.len() as u64
|
.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 current_process = if self.is_grouped() {
|
||||||
let group_pids = &self.canvas_data.finalized_process_data
|
let group_pids = &self
|
||||||
[self.currently_selected_process_position as usize]
|
.canvas_data
|
||||||
|
.finalized_process_data[self
|
||||||
|
.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position as usize]
|
||||||
.group_pids;
|
.group_pids;
|
||||||
|
|
||||||
let mut ret = ("".to_string(), group_pids.clone());
|
let mut ret = ("".to_string(), group_pids.clone());
|
||||||
@ -515,7 +543,10 @@ impl App {
|
|||||||
ret
|
ret
|
||||||
} else {
|
} else {
|
||||||
let process = self.canvas_data.finalized_process_data
|
let process = self.canvas_data.finalized_process_data
|
||||||
[self.currently_selected_process_position as usize]
|
[self
|
||||||
|
.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position as usize]
|
||||||
.clone();
|
.clone();
|
||||||
(process.name.clone(), vec![process.pid])
|
(process.name.clone(), vec![process.pid])
|
||||||
};
|
};
|
||||||
@ -525,20 +556,29 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.reset_multi_tap_keys();
|
self.reset_multi_tap_keys();
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_first_d {
|
||||||
self.awaiting_second_char = true;
|
self.awaiting_second_char = true;
|
||||||
self.second_char = 'd';
|
self.second_char = Some('d');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'g' => {
|
'g' => {
|
||||||
if self.awaiting_second_char && self.second_char == 'g' {
|
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.awaiting_second_char = false;
|
||||||
self.second_char = ' ';
|
self.second_char = None;
|
||||||
self.skip_to_first();
|
self.skip_to_first();
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_first_g {
|
||||||
self.awaiting_second_char = true;
|
self.awaiting_second_char = true;
|
||||||
self.second_char = 'g';
|
self.second_char = Some('g');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'G' => self.skip_to_last(),
|
'G' => self.skip_to_last(),
|
||||||
@ -558,7 +598,9 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
self.currently_selected_process_position = 0;
|
self.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position = 0;
|
||||||
}
|
}
|
||||||
'm' => {
|
'm' => {
|
||||||
match self.process_sorting_type {
|
match self.process_sorting_type {
|
||||||
@ -571,7 +613,9 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
self.currently_selected_process_position = 0;
|
self.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position = 0;
|
||||||
}
|
}
|
||||||
'p' => {
|
'p' => {
|
||||||
// Disable if grouping
|
// Disable if grouping
|
||||||
@ -586,7 +630,9 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
self.currently_selected_process_position = 0;
|
self.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'n' => {
|
'n' => {
|
||||||
@ -600,17 +646,22 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.update_process_gui = true;
|
self.update_process_gui = true;
|
||||||
self.currently_selected_process_position = 0;
|
self.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position = 0;
|
||||||
}
|
}
|
||||||
'?' => {
|
'?' => {
|
||||||
self.help_dialog_state.is_showing_help = true;
|
self.help_dialog_state.is_showing_help = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if self.awaiting_second_char && caught_char != self.second_char {
|
|
||||||
|
if let Some(second_char) = self.second_char {
|
||||||
|
if self.awaiting_second_char && caught_char != second_char {
|
||||||
self.awaiting_second_char = false;
|
self.awaiting_second_char = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if self.help_dialog_state.is_showing_help {
|
} else if self.help_dialog_state.is_showing_help {
|
||||||
match caught_char {
|
match caught_char {
|
||||||
'1' => self.help_dialog_state.current_category = AppHelpCategory::General,
|
'1' => self.help_dialog_state.current_category = AppHelpCategory::General,
|
||||||
@ -648,8 +699,8 @@ impl App {
|
|||||||
// Network -(up)> MEM, -(right)> PROC
|
// Network -(up)> MEM, -(right)> PROC
|
||||||
// PROC -(up)> Disk, -(down)> PROC_SEARCH, -(left)> Network
|
// PROC -(up)> Disk, -(down)> PROC_SEARCH, -(left)> Network
|
||||||
// PROC_SEARCH -(up)> PROC, -(left)> Network
|
// PROC_SEARCH -(up)> PROC, -(left)> Network
|
||||||
pub fn move_left(&mut self) {
|
pub fn move_widget_selection_left(&mut self) {
|
||||||
if !self.is_in_dialog() {
|
if !self.is_in_dialog() && !self.is_expanded {
|
||||||
self.current_widget_selected = match self.current_widget_selected {
|
self.current_widget_selected = match self.current_widget_selected {
|
||||||
WidgetPosition::Process => WidgetPosition::Network,
|
WidgetPosition::Process => WidgetPosition::Network,
|
||||||
WidgetPosition::ProcessSearch => WidgetPosition::Network,
|
WidgetPosition::ProcessSearch => WidgetPosition::Network,
|
||||||
@ -657,23 +708,25 @@ impl App {
|
|||||||
WidgetPosition::Temp => WidgetPosition::Mem,
|
WidgetPosition::Temp => WidgetPosition::Mem,
|
||||||
_ => self.current_widget_selected,
|
_ => self.current_widget_selected,
|
||||||
};
|
};
|
||||||
self.reset_multi_tap_keys();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_right(&mut self) {
|
self.reset_multi_tap_keys();
|
||||||
if !self.is_in_dialog() {
|
}
|
||||||
|
|
||||||
|
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 {
|
self.current_widget_selected = match self.current_widget_selected {
|
||||||
WidgetPosition::Mem => WidgetPosition::Temp,
|
WidgetPosition::Mem => WidgetPosition::Temp,
|
||||||
WidgetPosition::Network => WidgetPosition::Process,
|
WidgetPosition::Network => WidgetPosition::Process,
|
||||||
_ => self.current_widget_selected,
|
_ => self.current_widget_selected,
|
||||||
};
|
};
|
||||||
self.reset_multi_tap_keys();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_up(&mut self) {
|
self.reset_multi_tap_keys();
|
||||||
if !self.is_in_dialog() {
|
}
|
||||||
|
|
||||||
|
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 {
|
self.current_widget_selected = match self.current_widget_selected {
|
||||||
WidgetPosition::Mem => WidgetPosition::Cpu,
|
WidgetPosition::Mem => WidgetPosition::Cpu,
|
||||||
WidgetPosition::Network => WidgetPosition::Mem,
|
WidgetPosition::Network => WidgetPosition::Mem,
|
||||||
@ -683,12 +736,18 @@ impl App {
|
|||||||
WidgetPosition::Disk => WidgetPosition::Temp,
|
WidgetPosition::Disk => WidgetPosition::Temp,
|
||||||
_ => self.current_widget_selected,
|
_ => self.current_widget_selected,
|
||||||
};
|
};
|
||||||
self.reset_multi_tap_keys();
|
} else if self.is_expanded {
|
||||||
}
|
self.current_widget_selected = match self.current_widget_selected {
|
||||||
|
WidgetPosition::ProcessSearch => WidgetPosition::Process,
|
||||||
|
_ => self.current_widget_selected,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_down(&mut self) {
|
self.reset_multi_tap_keys();
|
||||||
if !self.is_in_dialog() {
|
}
|
||||||
|
|
||||||
|
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 {
|
self.current_widget_selected = match self.current_widget_selected {
|
||||||
WidgetPosition::Cpu => WidgetPosition::Mem,
|
WidgetPosition::Cpu => WidgetPosition::Mem,
|
||||||
WidgetPosition::Mem => WidgetPosition::Network,
|
WidgetPosition::Mem => WidgetPosition::Network,
|
||||||
@ -703,21 +762,49 @@ impl App {
|
|||||||
}
|
}
|
||||||
_ => self.current_widget_selected,
|
_ => self.current_widget_selected,
|
||||||
};
|
};
|
||||||
self.reset_multi_tap_keys();
|
} 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.reset_multi_tap_keys();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn skip_to_first(&mut self) {
|
pub fn skip_to_first(&mut self) {
|
||||||
if !self.is_in_dialog() {
|
if !self.is_in_dialog() {
|
||||||
match self.current_widget_selected {
|
match self.current_widget_selected {
|
||||||
WidgetPosition::Process => self.currently_selected_process_position = 0,
|
WidgetPosition::Process => {
|
||||||
WidgetPosition::Temp => self.currently_selected_temperature_position = 0,
|
self.app_scroll_positions
|
||||||
WidgetPosition::Disk => self.currently_selected_disk_position = 0,
|
.process_scroll_state
|
||||||
WidgetPosition::Cpu => self.currently_selected_cpu_table_position = 0,
|
.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
|
||||||
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.scroll_direction = ScrollDirection::UP;
|
self.app_scroll_positions.scroll_direction = ScrollDirection::UP;
|
||||||
self.reset_multi_tap_keys();
|
self.reset_multi_tap_keys();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,24 +813,28 @@ impl App {
|
|||||||
if !self.is_in_dialog() {
|
if !self.is_in_dialog() {
|
||||||
match self.current_widget_selected {
|
match self.current_widget_selected {
|
||||||
WidgetPosition::Process => {
|
WidgetPosition::Process => {
|
||||||
self.currently_selected_process_position =
|
self.app_scroll_positions
|
||||||
self.canvas_data.finalized_process_data.len() as u64 - 1
|
.process_scroll_state
|
||||||
|
.current_scroll_position = self.canvas_data.finalized_process_data.len() as u64 - 1
|
||||||
}
|
}
|
||||||
WidgetPosition::Temp => {
|
WidgetPosition::Temp => {
|
||||||
self.currently_selected_temperature_position =
|
self.app_scroll_positions
|
||||||
self.canvas_data.temp_sensor_data.len() as u64 - 1
|
.temp_scroll_state
|
||||||
|
.current_scroll_position = self.canvas_data.temp_sensor_data.len() as u64 - 1
|
||||||
}
|
}
|
||||||
WidgetPosition::Disk => {
|
WidgetPosition::Disk => {
|
||||||
self.currently_selected_disk_position =
|
self.app_scroll_positions
|
||||||
self.canvas_data.disk_data.len() as u64 - 1
|
.disk_scroll_state
|
||||||
|
.current_scroll_position = self.canvas_data.disk_data.len() as u64 - 1
|
||||||
}
|
}
|
||||||
WidgetPosition::Cpu => {
|
WidgetPosition::Cpu => {
|
||||||
self.currently_selected_cpu_table_position =
|
self.app_scroll_positions
|
||||||
self.canvas_data.cpu_data.len() as u64 - 1;
|
.cpu_scroll_state
|
||||||
|
.current_scroll_position = self.canvas_data.cpu_data.len() as u64 - 1;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.scroll_direction = ScrollDirection::DOWN;
|
self.app_scroll_positions.scroll_direction = ScrollDirection::DOWN;
|
||||||
self.reset_multi_tap_keys();
|
self.reset_multi_tap_keys();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -757,7 +848,7 @@ impl App {
|
|||||||
WidgetPosition::Cpu => self.change_cpu_table_position(-1), // TODO: [PO?] Temporary, may change if we add scaling
|
WidgetPosition::Cpu => self.change_cpu_table_position(-1), // TODO: [PO?] Temporary, may change if we add scaling
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.scroll_direction = ScrollDirection::UP;
|
self.app_scroll_positions.scroll_direction = ScrollDirection::UP;
|
||||||
self.reset_multi_tap_keys();
|
self.reset_multi_tap_keys();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,48 +862,70 @@ impl App {
|
|||||||
WidgetPosition::Cpu => self.change_cpu_table_position(1), // TODO: [PO?] Temporary, may change if we add scaling
|
WidgetPosition::Cpu => self.change_cpu_table_position(1), // TODO: [PO?] Temporary, may change if we add scaling
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.scroll_direction = ScrollDirection::DOWN;
|
self.app_scroll_positions.scroll_direction = ScrollDirection::DOWN;
|
||||||
self.reset_multi_tap_keys();
|
self.reset_multi_tap_keys();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
|
fn change_cpu_table_position(&mut self, num_to_change_by: i64) {
|
||||||
if self.currently_selected_cpu_table_position as i64 + num_to_change_by >= 0
|
let current_posn = self
|
||||||
&& self.currently_selected_cpu_table_position as i64 + num_to_change_by
|
.app_scroll_positions
|
||||||
< self.canvas_data.cpu_data.len() as i64
|
.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
|
||||||
{
|
{
|
||||||
self.currently_selected_cpu_table_position =
|
self.app_scroll_positions
|
||||||
(self.currently_selected_cpu_table_position as i64 + num_to_change_by) as u64;
|
.cpu_scroll_state
|
||||||
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_process_position(&mut self, num_to_change_by: i64) {
|
fn change_process_position(&mut self, num_to_change_by: i64) {
|
||||||
if self.currently_selected_process_position as i64 + num_to_change_by >= 0
|
let current_posn = self
|
||||||
&& self.currently_selected_process_position as i64 + num_to_change_by
|
.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
|
||||||
< self.canvas_data.finalized_process_data.len() as i64
|
< self.canvas_data.finalized_process_data.len() as i64
|
||||||
{
|
{
|
||||||
self.currently_selected_process_position =
|
self.app_scroll_positions
|
||||||
(self.currently_selected_process_position as i64 + num_to_change_by) as u64;
|
.process_scroll_state
|
||||||
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
||||||
if self.currently_selected_temperature_position as i64 + num_to_change_by >= 0
|
let current_posn = self
|
||||||
&& self.currently_selected_temperature_position as i64 + num_to_change_by
|
.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
|
||||||
< self.canvas_data.temp_sensor_data.len() as i64
|
< self.canvas_data.temp_sensor_data.len() as i64
|
||||||
{
|
{
|
||||||
self.currently_selected_temperature_position =
|
self.app_scroll_positions
|
||||||
(self.currently_selected_temperature_position as i64 + num_to_change_by) as u64;
|
.temp_scroll_state
|
||||||
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_disk_position(&mut self, num_to_change_by: i64) {
|
fn change_disk_position(&mut self, num_to_change_by: i64) {
|
||||||
if self.currently_selected_disk_position as i64 + num_to_change_by >= 0
|
let current_posn = self
|
||||||
&& self.currently_selected_disk_position as i64 + num_to_change_by
|
.app_scroll_positions
|
||||||
< self.canvas_data.disk_data.len() as i64
|
.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
|
||||||
{
|
{
|
||||||
self.currently_selected_disk_position =
|
self.app_scroll_positions
|
||||||
(self.currently_selected_disk_position as i64 + num_to_change_by) as u64;
|
.disk_scroll_state
|
||||||
|
.current_scroll_position = (current_posn as i64 + num_to_change_by) as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,8 @@ impl DataState {
|
|||||||
|
|
||||||
let current_instant = std::time::Instant::now();
|
let current_instant = std::time::Instant::now();
|
||||||
|
|
||||||
|
// TODO: [OPT] MT/Async the harvesting step.
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
self.data.network = network::get_network_data(
|
self.data.network = network::get_network_data(
|
||||||
&self.sys,
|
&self.sys,
|
||||||
|
176
src/canvas.rs
176
src/canvas.rs
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{self, data_harvester::processes::ProcessHarvest},
|
app::{self, data_harvester::processes::ProcessHarvest, WidgetPosition},
|
||||||
constants::*,
|
constants::*,
|
||||||
data_conversion::{ConvertedCpuData, ConvertedProcessData},
|
data_conversion::{ConvertedCpuData, ConvertedProcessData},
|
||||||
utils::error,
|
utils::error,
|
||||||
@ -146,9 +146,9 @@ impl Painter {
|
|||||||
.margin(1)
|
.margin(1)
|
||||||
.constraints(
|
.constraints(
|
||||||
[
|
[
|
||||||
Constraint::Percentage(32),
|
Constraint::Percentage(30),
|
||||||
Constraint::Percentage(36),
|
Constraint::Percentage(40),
|
||||||
Constraint::Percentage(32),
|
Constraint::Percentage(30),
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
@ -319,6 +319,72 @@ impl Painter {
|
|||||||
// This is a bit nasty, but it works well... I guess.
|
// This is a bit nasty, but it works well... I guess.
|
||||||
app_state.delete_dialog_state.is_showing_dd = false;
|
app_state.delete_dialog_state.is_showing_dd = false;
|
||||||
}
|
}
|
||||||
|
} else if app_state.is_expanded {
|
||||||
|
// TODO: [REF] we should combine this with normal drawing tbh
|
||||||
|
|
||||||
|
let rect = Layout::default()
|
||||||
|
.margin(1)
|
||||||
|
.constraints([Constraint::Percentage(100)].as_ref())
|
||||||
|
.split(f.size());
|
||||||
|
match &app_state.current_widget_selected {
|
||||||
|
WidgetPosition::Cpu => {
|
||||||
|
let cpu_chunk = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.margin(0)
|
||||||
|
.constraints(
|
||||||
|
if app_state.app_config_fields.left_legend {
|
||||||
|
[Constraint::Percentage(15), Constraint::Percentage(85)]
|
||||||
|
} else {
|
||||||
|
[Constraint::Percentage(85), Constraint::Percentage(15)]
|
||||||
|
}
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
|
.split(rect[0]);
|
||||||
|
|
||||||
|
let legend_index = if app_state.app_config_fields.left_legend {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
let graph_index = if app_state.app_config_fields.left_legend {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
self.draw_memory_graph(&mut f, &app_state, rect[0]);
|
||||||
|
}
|
||||||
|
WidgetPosition::Disk => {
|
||||||
|
self.draw_disk_table(&mut f, app_state, rect[0]);
|
||||||
|
}
|
||||||
|
WidgetPosition::Temp => {
|
||||||
|
self.draw_temp_table(&mut f, app_state, rect[0]);
|
||||||
|
}
|
||||||
|
WidgetPosition::Network => {
|
||||||
|
self.draw_network_graph(&mut f, &app_state, rect[0]);
|
||||||
|
}
|
||||||
|
WidgetPosition::Process | WidgetPosition::ProcessSearch => {
|
||||||
|
if app_state.is_searching() {
|
||||||
|
let processes_chunk = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.margin(0)
|
||||||
|
.constraints(
|
||||||
|
[Constraint::Percentage(85), Constraint::Percentage(15)]
|
||||||
|
.as_ref(),
|
||||||
|
)
|
||||||
|
.split(rect[0]);
|
||||||
|
|
||||||
|
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, rect[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases
|
// TODO: [TUI] Change this back to a more even 33/33/34 when TUI releases
|
||||||
let vertical_chunks = Layout::default()
|
let vertical_chunks = Layout::default()
|
||||||
@ -357,7 +423,7 @@ impl Painter {
|
|||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.margin(0)
|
.margin(0)
|
||||||
.constraints(
|
.constraints(
|
||||||
if app_state.left_legend {
|
if app_state.app_config_fields.left_legend {
|
||||||
[Constraint::Percentage(15), Constraint::Percentage(85)]
|
[Constraint::Percentage(15), Constraint::Percentage(85)]
|
||||||
} else {
|
} else {
|
||||||
[Constraint::Percentage(85), Constraint::Percentage(15)]
|
[Constraint::Percentage(85), Constraint::Percentage(15)]
|
||||||
@ -386,8 +452,16 @@ impl Painter {
|
|||||||
.split(bottom_chunks[0]);
|
.split(bottom_chunks[0]);
|
||||||
|
|
||||||
// Default chunk index based on left or right legend setting
|
// Default chunk index based on left or right legend setting
|
||||||
let legend_index = if app_state.left_legend { 0 } else { 1 };
|
let legend_index = if app_state.app_config_fields.left_legend {
|
||||||
let graph_index = if app_state.left_legend { 1 } else { 0 };
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
let graph_index = if app_state.app_config_fields.left_legend {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
// Set up blocks and their components
|
// Set up blocks and their components
|
||||||
// CPU graph
|
// CPU graph
|
||||||
@ -468,7 +542,7 @@ impl Painter {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if app_state.show_average_cpu {
|
if app_state.app_config_fields.show_average_cpu {
|
||||||
if let Some(avg_cpu_entry) = cpu_data.first() {
|
if let Some(avg_cpu_entry) = cpu_data.first() {
|
||||||
cpu_entries_vec.push((
|
cpu_entries_vec.push((
|
||||||
self.colours.cpu_colour_styles[0],
|
self.colours.cpu_colour_styles[0],
|
||||||
@ -484,7 +558,7 @@ impl Painter {
|
|||||||
for cpu_entry in &cpu_entries_vec {
|
for cpu_entry in &cpu_entries_vec {
|
||||||
dataset_vector.push(
|
dataset_vector.push(
|
||||||
Dataset::default()
|
Dataset::default()
|
||||||
.marker(if app_state.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
Marker::Braille
|
Marker::Braille
|
||||||
@ -519,9 +593,15 @@ impl Painter {
|
|||||||
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
||||||
let start_position = get_start_position(
|
let start_position = get_start_position(
|
||||||
num_rows,
|
num_rows,
|
||||||
&(app_state.scroll_direction),
|
&(app_state.app_scroll_positions.scroll_direction),
|
||||||
&mut app_state.previous_cpu_table_position,
|
&mut app_state
|
||||||
app_state.currently_selected_cpu_table_position,
|
.app_scroll_positions
|
||||||
|
.cpu_scroll_state
|
||||||
|
.previous_scroll_position,
|
||||||
|
app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.cpu_scroll_state
|
||||||
|
.current_scroll_position,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sliced_cpu_data = &cpu_data[start_position as usize..];
|
let sliced_cpu_data = &cpu_data[start_position as usize..];
|
||||||
@ -547,7 +627,10 @@ impl Painter {
|
|||||||
match app_state.current_widget_selected {
|
match app_state.current_widget_selected {
|
||||||
app::WidgetPosition::Cpu => {
|
app::WidgetPosition::Cpu => {
|
||||||
if cpu_row_counter as u64
|
if cpu_row_counter as u64
|
||||||
== app_state.currently_selected_cpu_table_position - start_position
|
== app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.cpu_scroll_state
|
||||||
|
.current_scroll_position - start_position
|
||||||
{
|
{
|
||||||
cpu_row_counter = -1;
|
cpu_row_counter = -1;
|
||||||
self.colours.currently_selected_text_style
|
self.colours.currently_selected_text_style
|
||||||
@ -612,7 +695,7 @@ impl Painter {
|
|||||||
|
|
||||||
let mut mem_canvas_vec: Vec<Dataset> = vec![Dataset::default()
|
let mut mem_canvas_vec: Vec<Dataset> = vec![Dataset::default()
|
||||||
.name(&app_state.canvas_data.mem_label)
|
.name(&app_state.canvas_data.mem_label)
|
||||||
.marker(if app_state.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
Marker::Braille
|
Marker::Braille
|
||||||
@ -624,7 +707,7 @@ impl Painter {
|
|||||||
mem_canvas_vec.push(
|
mem_canvas_vec.push(
|
||||||
Dataset::default()
|
Dataset::default()
|
||||||
.name(&app_state.canvas_data.swap_label)
|
.name(&app_state.canvas_data.swap_label)
|
||||||
.marker(if app_state.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
Marker::Braille
|
Marker::Braille
|
||||||
@ -682,7 +765,7 @@ impl Painter {
|
|||||||
"RX: {:7}",
|
"RX: {:7}",
|
||||||
app_state.canvas_data.rx_display.clone()
|
app_state.canvas_data.rx_display.clone()
|
||||||
))
|
))
|
||||||
.marker(if app_state.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
Marker::Braille
|
Marker::Braille
|
||||||
@ -694,13 +777,21 @@ impl Painter {
|
|||||||
"TX: {:7}",
|
"TX: {:7}",
|
||||||
app_state.canvas_data.tx_display.clone()
|
app_state.canvas_data.tx_display.clone()
|
||||||
))
|
))
|
||||||
.marker(if app_state.use_dot {
|
.marker(if app_state.app_config_fields.use_dot {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
Marker::Braille
|
Marker::Braille
|
||||||
})
|
})
|
||||||
.style(self.colours.tx_style)
|
.style(self.colours.tx_style)
|
||||||
.data(&network_data_tx),
|
.data(&network_data_tx),
|
||||||
|
Dataset::default().name(&format!(
|
||||||
|
"Total RX: {:7}",
|
||||||
|
app_state.canvas_data.total_rx_display.clone()
|
||||||
|
)),
|
||||||
|
Dataset::default().name(&format!(
|
||||||
|
"Total TX: {:7}",
|
||||||
|
app_state.canvas_data.total_tx_display.clone()
|
||||||
|
)),
|
||||||
])
|
])
|
||||||
.render(f, draw_loc);
|
.render(f, draw_loc);
|
||||||
}
|
}
|
||||||
@ -763,9 +854,15 @@ impl Painter {
|
|||||||
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
||||||
let start_position = get_start_position(
|
let start_position = get_start_position(
|
||||||
num_rows,
|
num_rows,
|
||||||
&(app_state.scroll_direction),
|
&(app_state.app_scroll_positions.scroll_direction),
|
||||||
&mut app_state.previous_temp_position,
|
&mut app_state
|
||||||
app_state.currently_selected_temperature_position,
|
.app_scroll_positions
|
||||||
|
.temp_scroll_state
|
||||||
|
.previous_scroll_position,
|
||||||
|
app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.temp_scroll_state
|
||||||
|
.current_scroll_position,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sliced_vec = &(temp_sensor_data[start_position as usize..]);
|
let sliced_vec = &(temp_sensor_data[start_position as usize..]);
|
||||||
@ -777,7 +874,10 @@ impl Painter {
|
|||||||
match app_state.current_widget_selected {
|
match app_state.current_widget_selected {
|
||||||
app::WidgetPosition::Temp => {
|
app::WidgetPosition::Temp => {
|
||||||
if temp_row_counter as u64
|
if temp_row_counter as u64
|
||||||
== app_state.currently_selected_temperature_position - start_position
|
== app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.temp_scroll_state
|
||||||
|
.current_scroll_position - start_position
|
||||||
{
|
{
|
||||||
temp_row_counter = -1;
|
temp_row_counter = -1;
|
||||||
self.colours.currently_selected_text_style
|
self.colours.currently_selected_text_style
|
||||||
@ -829,9 +929,15 @@ impl Painter {
|
|||||||
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
let num_rows = max(0, i64::from(draw_loc.height) - 5) as u64;
|
||||||
let start_position = get_start_position(
|
let start_position = get_start_position(
|
||||||
num_rows,
|
num_rows,
|
||||||
&(app_state.scroll_direction),
|
&(app_state.app_scroll_positions.scroll_direction),
|
||||||
&mut app_state.previous_disk_position,
|
&mut app_state
|
||||||
app_state.currently_selected_disk_position,
|
.app_scroll_positions
|
||||||
|
.disk_scroll_state
|
||||||
|
.previous_scroll_position,
|
||||||
|
app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.disk_scroll_state
|
||||||
|
.current_scroll_position,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sliced_vec = &disk_data[start_position as usize..];
|
let sliced_vec = &disk_data[start_position as usize..];
|
||||||
@ -843,7 +949,10 @@ impl Painter {
|
|||||||
match app_state.current_widget_selected {
|
match app_state.current_widget_selected {
|
||||||
app::WidgetPosition::Disk => {
|
app::WidgetPosition::Disk => {
|
||||||
if disk_counter as u64
|
if disk_counter as u64
|
||||||
== app_state.currently_selected_disk_position - start_position
|
== app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.disk_scroll_state
|
||||||
|
.current_scroll_position - start_position
|
||||||
{
|
{
|
||||||
disk_counter = -1;
|
disk_counter = -1;
|
||||||
self.colours.currently_selected_text_style
|
self.colours.currently_selected_text_style
|
||||||
@ -1029,9 +1138,15 @@ impl Painter {
|
|||||||
|
|
||||||
let position = get_start_position(
|
let position = get_start_position(
|
||||||
num_rows,
|
num_rows,
|
||||||
&(app_state.scroll_direction),
|
&(app_state.app_scroll_positions.scroll_direction),
|
||||||
&mut app_state.previous_process_position,
|
&mut app_state
|
||||||
app_state.currently_selected_process_position,
|
.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.previous_scroll_position,
|
||||||
|
app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
@ -1061,7 +1176,10 @@ impl Painter {
|
|||||||
match app_state.current_widget_selected {
|
match app_state.current_widget_selected {
|
||||||
app::WidgetPosition::Process => {
|
app::WidgetPosition::Process => {
|
||||||
if process_counter as u64
|
if process_counter as u64
|
||||||
== app_state.currently_selected_process_position - start_position
|
== app_state
|
||||||
|
.app_scroll_positions
|
||||||
|
.process_scroll_state
|
||||||
|
.current_scroll_position - start_position
|
||||||
{
|
{
|
||||||
process_counter = -1;
|
process_counter = -1;
|
||||||
self.colours.currently_selected_text_style
|
self.colours.currently_selected_text_style
|
||||||
|
@ -12,7 +12,7 @@ pub const DEFAULT_UNIX_CONFIG_FILE_PATH: &str = "~/.config/btm/btm.toml";
|
|||||||
pub const DEFAULT_WINDOWS_CONFIG_FILE_PATH: &str = "";
|
pub const DEFAULT_WINDOWS_CONFIG_FILE_PATH: &str = "";
|
||||||
|
|
||||||
// Help text
|
// Help text
|
||||||
pub const GENERAL_HELP_TEXT: [&str; 15] = [
|
pub const GENERAL_HELP_TEXT: [&str; 16] = [
|
||||||
"General Keybindings\n\n",
|
"General Keybindings\n\n",
|
||||||
"Esc Close dialog box\n",
|
"Esc Close dialog box\n",
|
||||||
"q, Ctrl-c Quit bottom\n",
|
"q, Ctrl-c Quit bottom\n",
|
||||||
@ -28,6 +28,7 @@ pub const GENERAL_HELP_TEXT: [&str; 15] = [
|
|||||||
"? Open the help screen\n",
|
"? Open the help screen\n",
|
||||||
"gg Skip to the first entry of a list\n",
|
"gg Skip to the first entry of a list\n",
|
||||||
"G Skip to the last entry of a list\n",
|
"G Skip to the last entry of a list\n",
|
||||||
|
"Enter Maximize the currently selected widget\n",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const PROCESS_HELP_TEXT: [&str; 8] = [
|
pub const PROCESS_HELP_TEXT: [&str; 8] = [
|
||||||
|
@ -62,7 +62,7 @@ pub fn convert_temp_row(app: &App) -> Vec<Vec<String>> {
|
|||||||
let mut sensor_vector: Vec<Vec<String>> = Vec::new();
|
let mut sensor_vector: Vec<Vec<String>> = Vec::new();
|
||||||
|
|
||||||
let current_data = &app.data_collection;
|
let current_data = &app.data_collection;
|
||||||
let temp_type = &app.temperature_type;
|
let temp_type = &app.app_config_fields.temperature_type;
|
||||||
|
|
||||||
if current_data.temp_harvest.is_empty() {
|
if current_data.temp_harvest.is_empty() {
|
||||||
sensor_vector.push(vec!["No Sensors Found".to_string(), "".to_string()])
|
sensor_vector.push(vec!["No Sensors Found".to_string(), "".to_string()])
|
||||||
|
42
src/main.rs
42
src/main.rs
@ -182,7 +182,7 @@ fn main() -> error::Result<()> {
|
|||||||
rrx,
|
rrx,
|
||||||
use_current_cpu_total,
|
use_current_cpu_total,
|
||||||
update_rate_in_milliseconds as u64,
|
update_rate_in_milliseconds as u64,
|
||||||
app.temperature_type.clone(),
|
app.app_config_fields.temperature_type.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut painter = canvas::Painter::default();
|
let mut painter = canvas::Painter::default();
|
||||||
@ -214,6 +214,8 @@ fn main() -> error::Result<()> {
|
|||||||
|
|
||||||
// Convert all data into tui-compliant components
|
// Convert all data into tui-compliant components
|
||||||
|
|
||||||
|
// TODO: [OPT] MT the conversion step.
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
let network_data = convert_network_data_points(&app.data_collection);
|
let network_data = convert_network_data_points(&app.data_collection);
|
||||||
app.canvas_data.network_data_rx = network_data.rx;
|
app.canvas_data.network_data_rx = network_data.rx;
|
||||||
@ -236,8 +238,10 @@ fn main() -> error::Result<()> {
|
|||||||
app.canvas_data.swap_label = memory_and_swap_labels.1;
|
app.canvas_data.swap_label = memory_and_swap_labels.1;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
app.canvas_data.cpu_data =
|
app.canvas_data.cpu_data = convert_cpu_data_points(
|
||||||
convert_cpu_data_points(app.show_average_cpu, &app.data_collection);
|
app.app_config_fields.show_average_cpu,
|
||||||
|
&app.data_collection,
|
||||||
|
);
|
||||||
|
|
||||||
// Processes
|
// Processes
|
||||||
let (single, grouped) = convert_process_data(&app.data_collection);
|
let (single, grouped) = convert_process_data(&app.data_collection);
|
||||||
@ -294,10 +298,10 @@ fn handle_key_event_or_break(
|
|||||||
KeyCode::Down => app.on_down_key(),
|
KeyCode::Down => app.on_down_key(),
|
||||||
KeyCode::Left => app.on_left_key(),
|
KeyCode::Left => app.on_left_key(),
|
||||||
KeyCode::Right => app.on_right_key(),
|
KeyCode::Right => app.on_right_key(),
|
||||||
KeyCode::Char('H') => app.move_left(),
|
KeyCode::Char('H') => app.move_widget_selection_left(),
|
||||||
KeyCode::Char('L') => app.move_right(),
|
KeyCode::Char('L') => app.move_widget_selection_right(),
|
||||||
KeyCode::Char('K') => app.move_up(),
|
KeyCode::Char('K') => app.move_widget_selection_up(),
|
||||||
KeyCode::Char('J') => app.move_down(),
|
KeyCode::Char('J') => app.move_widget_selection_down(),
|
||||||
KeyCode::Char(character) => app.on_char_key(character),
|
KeyCode::Char(character) => app.on_char_key(character),
|
||||||
KeyCode::Esc => app.on_esc(),
|
KeyCode::Esc => app.on_esc(),
|
||||||
KeyCode::Enter => app.on_enter(),
|
KeyCode::Enter => app.on_enter(),
|
||||||
@ -314,10 +318,10 @@ fn handle_key_event_or_break(
|
|||||||
|
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Char('f') => app.enable_searching(),
|
KeyCode::Char('f') => app.enable_searching(),
|
||||||
KeyCode::Left => app.move_left(),
|
KeyCode::Left => app.move_widget_selection_left(),
|
||||||
KeyCode::Right => app.move_right(),
|
KeyCode::Right => app.move_widget_selection_right(),
|
||||||
KeyCode::Up => app.move_up(),
|
KeyCode::Up => app.move_widget_selection_up(),
|
||||||
KeyCode::Down => app.move_down(),
|
KeyCode::Down => app.move_widget_selection_down(),
|
||||||
KeyCode::Char('r') => {
|
KeyCode::Char('r') => {
|
||||||
if rtx.send(ResetEvent::Reset).is_ok() {
|
if rtx.send(ResetEvent::Reset).is_ok() {
|
||||||
app.reset();
|
app.reset();
|
||||||
@ -329,10 +333,18 @@ fn handle_key_event_or_break(
|
|||||||
}
|
}
|
||||||
} else if let KeyModifiers::SHIFT = event.modifiers {
|
} else if let KeyModifiers::SHIFT = event.modifiers {
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Left | KeyCode::Char('h') | KeyCode::Char('H') => app.move_left(),
|
KeyCode::Left | KeyCode::Char('h') | KeyCode::Char('H') => {
|
||||||
KeyCode::Right | KeyCode::Char('l') | KeyCode::Char('L') => app.move_right(),
|
app.move_widget_selection_left()
|
||||||
KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => app.move_up(),
|
}
|
||||||
KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => app.move_down(),
|
KeyCode::Right | KeyCode::Char('l') | KeyCode::Char('L') => {
|
||||||
|
app.move_widget_selection_right()
|
||||||
|
}
|
||||||
|
KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => {
|
||||||
|
app.move_widget_selection_up()
|
||||||
|
}
|
||||||
|
KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => {
|
||||||
|
app.move_widget_selection_down()
|
||||||
|
}
|
||||||
KeyCode::Char('/') | KeyCode::Char('?') => app.on_char_key('?'),
|
KeyCode::Char('/') | KeyCode::Char('?') => app.on_char_key('?'),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user