From 8e4f6a3a02401bd7625e4ce7e087adc0750a538e Mon Sep 17 00:00:00 2001 From: ClementTsang Date: Mon, 27 Apr 2020 15:52:39 -0400 Subject: [PATCH] feature: add battery flag --- README.md | 9 +- src/app.rs | 2 + src/app/layout_manager.rs | 317 +++++++++++++++-------- src/canvas.rs | 18 +- src/canvas/widgets/basic_table_arrows.rs | 52 ++-- src/canvas/widgets/battery_display.rs | 36 ++- src/canvas/widgets/temp_table.rs | 6 +- src/options.rs | 6 +- 8 files changed, 301 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 3171a8fa..06db149a 100644 --- a/README.md +++ b/README.md @@ -143,20 +143,21 @@ Run using `btm`. -s, --show_disabled_data Shows disabled CPU entries in the CPU legend -b, --basic Enables basic mode, removing charts and condensing data --autohide_time Automatically hide the time scaling in graphs after being shown for a brief moment when - zoomed in/out. If time is disabled via --hide_time then this will have no effect. + zoomed in/out. If time is disabled via --hide_time then this will have no effect --use_old_network_legend Use the older (pre-0.4) network legend which is separate from the network chart --hide_table_gap Hides the spacing between table headers and data + --battery Displays the battery widget for default and basic layouts ``` ### Options ``` -r, --rate Set the refresh rate in milliseconds [default: 1000] --C, --config Use the specified config file; if it does not exist it is automatically created +-C, --config Use the specified config file; if it does not exist it is automatically created [default: see section on config files] -t, --default_time_value Sets the default time interval for charts in milliseconds [default: 60000] -d, --time_delta Sets the default amount each zoom in/out action changes by in milliseconds [default: 15000] - --default_widget_count Which number of the selected widget type to select, from left to right, top to bottom. Defaults to 1. - --default_widget_type The default widget type to select by default. + --default_widget_count Which number of the selected widget type to select, from left to right, top to bottom [default: 1] + --default_widget_type The default widget type to select by default [default: "process"] ``` ### Keybindings diff --git a/src/app.rs b/src/app.rs index 227f0231..b312bc2a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1213,6 +1213,7 @@ impl App { | BottomWidgetType::Proc | BottomWidgetType::ProcSearch | BottomWidgetType::Disk + | BottomWidgetType::Battery if self.basic_table_widget_state.is_some() => { if let Some(basic_table_widget_state) = @@ -1311,6 +1312,7 @@ impl App { | BottomWidgetType::Proc | BottomWidgetType::ProcSearch | BottomWidgetType::Disk + | BottomWidgetType::Battery if self.basic_table_widget_state.is_some() => { if let Some(basic_table_widget_state) = diff --git a/src/app/layout_manager.rs b/src/app/layout_manager.rs index 60a241e2..6cd27150 100644 --- a/src/app/layout_manager.rs +++ b/src/app/layout_manager.rs @@ -510,7 +510,141 @@ impl BottomLayout { } } - pub fn init_basic_default() -> Self { + pub fn init_basic_default(use_battery: bool) -> Self { + let table_widgets = if use_battery { + vec![ + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Disk) + .widget_id(4) + .up_neighbour(Some(100)) + .left_neighbour(Some(8)) + .right_neighbour(Some(DEFAULT_WIDGET_ID)) + .build()]) + .build()]) + .build(), + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![ + BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Proc) + .widget_id(DEFAULT_WIDGET_ID) + .up_neighbour(Some(100)) + .down_neighbour(Some(DEFAULT_WIDGET_ID + 1)) + .left_neighbour(Some(4)) + .right_neighbour(Some(8)) + .build()]) + .build(), + BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::ProcSearch) + .widget_id(DEFAULT_WIDGET_ID + 1) + .up_neighbour(Some(DEFAULT_WIDGET_ID)) + .left_neighbour(Some(4)) + .right_neighbour(Some(7)) + .build()]) + .build(), + ]) + .build(), + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Temp) + .widget_id(7) + .up_neighbour(Some(100)) + .left_neighbour(Some(DEFAULT_WIDGET_ID)) + .right_neighbour(Some(8)) + .build()]) + .build()]) + .build(), + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Battery) + .widget_id(8) + .up_neighbour(Some(100)) + .left_neighbour(Some(7)) + .right_neighbour(Some(4)) + .build()]) + .build()]) + .build(), + ] + } else { + vec![ + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Disk) + .widget_id(4) + .up_neighbour(Some(100)) + .left_neighbour(Some(7)) + .right_neighbour(Some(DEFAULT_WIDGET_ID)) + .build()]) + .build()]) + .build(), + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![ + BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Proc) + .widget_id(DEFAULT_WIDGET_ID) + .up_neighbour(Some(100)) + .down_neighbour(Some(DEFAULT_WIDGET_ID + 1)) + .left_neighbour(Some(4)) + .right_neighbour(Some(7)) + .build()]) + .build(), + BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::ProcSearch) + .widget_id(DEFAULT_WIDGET_ID + 1) + .up_neighbour(Some(DEFAULT_WIDGET_ID)) + .left_neighbour(Some(4)) + .right_neighbour(Some(7)) + .build()]) + .build(), + ]) + .build(), + BottomCol::builder() + .canvas_handle_width(true) + .children(vec![BottomColRow::builder() + .canvas_handle_height(true) + .children(vec![BottomWidget::builder() + .canvas_handle_width(true) + .widget_type(BottomWidgetType::Temp) + .widget_id(7) + .up_neighbour(Some(100)) + .left_neighbour(Some(DEFAULT_WIDGET_ID)) + .right_neighbour(Some(4)) + .build()]) + .build()]) + .build(), + ] + }; + BottomLayout { total_row_height_ratio: 3, rows: vec![ @@ -573,119 +707,93 @@ impl BottomLayout { .build(), BottomRow::builder() .canvas_handle_height(true) - .children(vec![ - BottomCol::builder() - .canvas_handle_width(true) - .children(vec![BottomColRow::builder() - .canvas_handle_height(true) - .children(vec![BottomWidget::builder() - .canvas_handle_width(true) - .widget_type(BottomWidgetType::Disk) - .widget_id(4) - .up_neighbour(Some(100)) - .left_neighbour(Some(7)) - .right_neighbour(Some(DEFAULT_WIDGET_ID)) - .build()]) - .build()]) - .build(), - BottomCol::builder() - .canvas_handle_width(true) - .children(vec![ - BottomColRow::builder() - .canvas_handle_height(true) - .children(vec![BottomWidget::builder() - .canvas_handle_width(true) - .widget_type(BottomWidgetType::Proc) - .widget_id(DEFAULT_WIDGET_ID) - .up_neighbour(Some(100)) - .down_neighbour(Some(DEFAULT_WIDGET_ID + 1)) - .left_neighbour(Some(4)) - .right_neighbour(Some(7)) - .build()]) - .build(), - BottomColRow::builder() - .canvas_handle_height(true) - .children(vec![BottomWidget::builder() - .canvas_handle_width(true) - .widget_type(BottomWidgetType::ProcSearch) - .widget_id(DEFAULT_WIDGET_ID + 1) - .up_neighbour(Some(DEFAULT_WIDGET_ID)) - .left_neighbour(Some(4)) - .right_neighbour(Some(7)) - .build()]) - .build(), - ]) - .build(), - BottomCol::builder() - .canvas_handle_width(true) - .children(vec![BottomColRow::builder() - .canvas_handle_height(true) - .children(vec![BottomWidget::builder() - .canvas_handle_width(true) - .widget_type(BottomWidgetType::Temp) - .widget_id(7) - .up_neighbour(Some(100)) - .left_neighbour(Some(DEFAULT_WIDGET_ID)) - .right_neighbour(Some(4)) - .build()]) - .build()]) - .build(), - ]) + .children(table_widgets) .build(), ], } } - pub fn init_default(left_legend: bool) -> Self { + pub fn init_default(left_legend: bool, use_battery: bool) -> Self { + let cpu_layout = if left_legend { + vec![ + BottomWidget::builder() + .width_ratio(3) + .widget_type(BottomWidgetType::CpuLegend) + .widget_id(2) + .down_neighbour(Some(11)) + .right_neighbour(Some(1)) + .canvas_handle_width(true) + .build(), + BottomWidget::builder() + .width_ratio(17) + .widget_type(BottomWidgetType::Cpu) + .widget_id(1) + .down_neighbour(Some(12)) + .left_neighbour(Some(2)) + .right_neighbour(if use_battery { Some(99) } else { None }) + .flex_grow(true) + .build(), + ] + } else { + vec![ + BottomWidget::builder() + .width_ratio(17) + .widget_type(BottomWidgetType::Cpu) + .widget_id(1) + .down_neighbour(Some(11)) + .right_neighbour(Some(2)) + .flex_grow(true) + .build(), + BottomWidget::builder() + .width_ratio(3) + .widget_type(BottomWidgetType::CpuLegend) + .widget_id(2) + .down_neighbour(Some(12)) + .left_neighbour(Some(1)) + .right_neighbour(if use_battery { Some(99) } else { None }) + .canvas_handle_width(true) + .build(), + ] + }; + + let first_row_layout = if use_battery { + vec![ + BottomCol::builder() + .col_width_ratio(2) + .children(vec![BottomColRow::builder() + .total_widget_ratio(20) + .children(cpu_layout) + .build()]) + .build(), + BottomCol::builder() + .col_width_ratio(1) + .children(vec![BottomColRow::builder() + .children(vec![BottomWidget::builder() + .widget_type(BottomWidgetType::Battery) + .widget_id(99) + .down_neighbour(Some(12)) + .left_neighbour(Some(if left_legend { 1 } else { 2 })) + .canvas_handle_width(true) + .build()]) + .build()]) + .build(), + ] + } else { + vec![BottomCol::builder() + .children(vec![BottomColRow::builder() + .total_widget_ratio(20) + .children(cpu_layout) + .build()]) + .build()] + }; + BottomLayout { total_row_height_ratio: 100, rows: vec![ BottomRow::builder() .row_height_ratio(30) - .children(vec![BottomCol::builder() - .children(vec![BottomColRow::builder() - .total_widget_ratio(20) - .children(if left_legend { - vec![ - BottomWidget::builder() - .width_ratio(3) - .widget_type(BottomWidgetType::CpuLegend) - .widget_id(2) - .down_neighbour(Some(11)) - .right_neighbour(Some(1)) - .canvas_handle_width(true) - .build(), - BottomWidget::builder() - .width_ratio(17) - .widget_type(BottomWidgetType::Cpu) - .widget_id(1) - .down_neighbour(Some(12)) - .left_neighbour(Some(2)) - .flex_grow(true) - .build(), - ] - } else { - vec![ - BottomWidget::builder() - .width_ratio(17) - .widget_type(BottomWidgetType::Cpu) - .widget_id(1) - .down_neighbour(Some(11)) - .right_neighbour(Some(2)) - .flex_grow(true) - .build(), - BottomWidget::builder() - .width_ratio(3) - .widget_type(BottomWidgetType::CpuLegend) - .widget_id(2) - .down_neighbour(Some(12)) - .left_neighbour(Some(1)) - .canvas_handle_width(true) - .build(), - ] - }) - .build()]) - .build()]) + .total_col_ratio(if use_battery { 3 } else { 1 }) + .children(first_row_layout) .build(), BottomRow::builder() .total_col_ratio(7) @@ -907,6 +1015,7 @@ impl BottomWidgetType { Proc => "Processes", Temp => "Temperature", Disk => "Disks", + Battery => "Battery", _ => "", } } diff --git a/src/canvas.rs b/src/canvas.rs index a603faa3..9c598567 100644 --- a/src/canvas.rs +++ b/src/canvas.rs @@ -350,6 +350,7 @@ impl Painter { &mut f, app_state, rect[0], + true, app_state.current_widget.widget_id, ), _ => {} @@ -410,6 +411,13 @@ impl Painter { false, widget_id, ), + Battery => self.draw_battery_display( + &mut f, + app_state, + vertical_chunks[4], + false, + widget_id, + ), _ => {} } } @@ -541,9 +549,13 @@ impl Painter { true, widget.widget_id, ), - Battery => { - self.draw_battery_display(f, app_state, *widget_draw_loc, widget.widget_id) - } + Battery => self.draw_battery_display( + f, + app_state, + *widget_draw_loc, + true, + widget.widget_id, + ), _ => {} } } diff --git a/src/canvas/widgets/basic_table_arrows.rs b/src/canvas/widgets/basic_table_arrows.rs index 8284c691..554d7690 100644 --- a/src/canvas/widgets/basic_table_arrows.rs +++ b/src/canvas/widgets/basic_table_arrows.rs @@ -23,19 +23,38 @@ impl BasicTableArrows for Painter { &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, ) { // Effectively a paragraph with a ton of spacing - let (left_table, right_table) = - if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state { - match basic_table_widget_state.currently_displayed_widget_type { - BottomWidgetType::Proc | BottomWidgetType::ProcSearch => { - (BottomWidgetType::Temp, BottomWidgetType::Disk) - } - BottomWidgetType::Disk => (BottomWidgetType::Proc, BottomWidgetType::Temp), - BottomWidgetType::Temp => (BottomWidgetType::Disk, BottomWidgetType::Proc), - _ => (BottomWidgetType::Disk, BottomWidgetType::Temp), - } - } else { - (BottomWidgetType::Disk, BottomWidgetType::Temp) - }; + let (left_table, right_table) = ( + { + app_state + .current_widget + .left_neighbour + .and_then(|left_widget_id| { + Some( + app_state + .widget_map + .get(&left_widget_id) + .and_then(|left_widget| Some(&left_widget.widget_type)) + .unwrap_or_else(|| &BottomWidgetType::Temp), + ) + }) + .unwrap_or_else(|| &BottomWidgetType::Temp) + }, + { + app_state + .current_widget + .right_neighbour + .and_then(|right_widget_id| { + Some( + app_state + .widget_map + .get(&right_widget_id) + .and_then(|right_widget| Some(&right_widget.widget_type)) + .unwrap_or_else(|| &BottomWidgetType::Disk), + ) + }) + .unwrap_or_else(|| &BottomWidgetType::Disk) + }, + ); let left_name = left_table.get_pretty_name(); let right_name = right_table.get_pretty_name(); @@ -46,12 +65,9 @@ impl BasicTableArrows for Painter { ) as usize; let arrow_text = vec![ - Text::Styled( - format!("\n◄ {}", right_name).into(), - self.colours.text_style, - ), + Text::Styled(format!("\n◄ {}", left_name).into(), self.colours.text_style), Text::Raw(" ".repeat(num_spaces).into()), - Text::Styled(format!("{} ►", left_name).into(), self.colours.text_style), + Text::Styled(format!("{} ►", right_name).into(), self.colours.text_style), ]; let margined_draw_loc = Layout::default() diff --git a/src/canvas/widgets/battery_display.rs b/src/canvas/widgets/battery_display.rs index a31281f4..8d4c7a5f 100644 --- a/src/canvas/widgets/battery_display.rs +++ b/src/canvas/widgets/battery_display.rs @@ -3,6 +3,7 @@ use std::cmp::max; use crate::{ app::App, canvas::{drawing_utils::calculate_basic_use_bars, Painter}, + constants::*, }; use tui::{ @@ -14,17 +15,20 @@ use tui::{ pub trait BatteryDisplayWidget { fn draw_battery_display( - &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64, + &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool, + widget_id: u64, ); } impl BatteryDisplayWidget for Painter { fn draw_battery_display( - &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, widget_id: u64, + &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool, + widget_id: u64, ) { if let Some(battery_widget_state) = app_state.battery_state.widget_states.get_mut(&widget_id) { + let is_on_widget = widget_id == app_state.current_widget.widget_id; let title = if app_state.is_expanded { const TITLE_BASE: &str = " Battery ── Esc to go back "; let repeat_num = max( @@ -40,21 +44,29 @@ impl BatteryDisplayWidget for Painter { " Battery ".to_string() }; - let border_and_title_style = if app_state.current_widget.widget_id == widget_id { + let border_and_title_style = if is_on_widget { self.colours.highlighted_border_style } else { self.colours.border_style }; - let battery_block = Block::default() - .title(&title) - .title_style(if app_state.is_expanded { - border_and_title_style - } else { - self.colours.widget_title_style - }) - .borders(Borders::ALL) - .border_style(border_and_title_style); + let battery_block = if draw_border { + Block::default() + .title(&title) + .title_style(if app_state.is_expanded { + border_and_title_style + } else { + self.colours.widget_title_style + }) + .borders(Borders::ALL) + .border_style(border_and_title_style) + } else if is_on_widget { + Block::default() + .borders(*SIDE_BORDERS) + .border_style(self.colours.highlighted_border_style) + } else { + Block::default().borders(Borders::NONE) + }; if let Some(battery_details) = app_state .canvas_data diff --git a/src/canvas/widgets/temp_table.rs b/src/canvas/widgets/temp_table.rs index 1e679904..32b35733 100644 --- a/src/canvas/widgets/temp_table.rs +++ b/src/canvas/widgets/temp_table.rs @@ -94,7 +94,11 @@ impl TempTableWidget for Painter { let temp_block = if draw_border { Block::default() .title(&title) - .title_style(border_and_title_style) + .title_style(if app_state.is_expanded { + border_and_title_style + } else { + self.colours.widget_title_style + }) .borders(Borders::ALL) .border_style(border_and_title_style) } else if is_on_widget { diff --git a/src/options.rs b/src/options.rs index 7351f4c4..d7a32f1f 100644 --- a/src/options.rs +++ b/src/options.rs @@ -262,7 +262,7 @@ pub fn get_widget_layout( let bottom_layout = if get_use_basic_mode(matches, config) { default_widget_id = DEFAULT_WIDGET_ID; - BottomLayout::init_basic_default() + BottomLayout::init_basic_default(get_use_battery(matches, config)) } else if let Some(rows) = &config.row { let mut iter_id = 0; // A lazy way of forcing unique IDs *shrugs* let mut total_height_ratio = 0; @@ -284,7 +284,7 @@ pub fn get_widget_layout( total_row_height_ratio: total_height_ratio, }; - // Confirm that we have at least ONE widget - if we don't, go back to default! + // Confirm that we have at least ONE widget - if not, error out! if iter_id > 0 { ret_bottom_layout.get_movement_mappings(); ret_bottom_layout @@ -295,7 +295,7 @@ pub fn get_widget_layout( } } else { default_widget_id = DEFAULT_WIDGET_ID; - BottomLayout::init_default(left_legend) + BottomLayout::init_default(left_legend, get_use_battery(matches, config)) }; Ok((bottom_layout, default_widget_id))