feature: add battery flag

This commit is contained in:
ClementTsang 2020-04-27 15:52:39 -04:00
parent 8534d42f1b
commit 8e4f6a3a02
8 changed files with 301 additions and 145 deletions

View File

@ -143,20 +143,21 @@ Run using `btm`.
-s, --show_disabled_data Shows disabled CPU entries in the CPU legend -s, --show_disabled_data Shows disabled CPU entries in the CPU legend
-b, --basic Enables basic mode, removing charts and condensing data -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 --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 --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 --hide_table_gap Hides the spacing between table headers and data
--battery Displays the battery widget for default and basic layouts
``` ```
### Options ### Options
``` ```
-r, --rate <MS> Set the refresh rate in milliseconds [default: 1000] -r, --rate <MS> Set the refresh rate in milliseconds [default: 1000]
-C, --config <PATH> Use the specified config file; if it does not exist it is automatically created -C, --config <PATH> Use the specified config file; if it does not exist it is automatically created [default: see section on config files]
-t, --default_time_value <MS> Sets the default time interval for charts in milliseconds [default: 60000] -t, --default_time_value <MS> Sets the default time interval for charts in milliseconds [default: 60000]
-d, --time_delta <MS> Sets the default amount each zoom in/out action changes by in milliseconds [default: 15000] -d, --time_delta <MS> Sets the default amount each zoom in/out action changes by in milliseconds [default: 15000]
--default_widget_count <COUNT> Which number of the selected widget type to select, from left to right, top to bottom. Defaults to 1. --default_widget_count <COUNT> Which number of the selected widget type to select, from left to right, top to bottom [default: 1]
--default_widget_type <TYPE> The default widget type to select by default. --default_widget_type <TYPE> The default widget type to select by default [default: "process"]
``` ```
### Keybindings ### Keybindings

View File

@ -1213,6 +1213,7 @@ impl App {
| BottomWidgetType::Proc | BottomWidgetType::Proc
| BottomWidgetType::ProcSearch | BottomWidgetType::ProcSearch
| BottomWidgetType::Disk | BottomWidgetType::Disk
| BottomWidgetType::Battery
if self.basic_table_widget_state.is_some() => if self.basic_table_widget_state.is_some() =>
{ {
if let Some(basic_table_widget_state) = if let Some(basic_table_widget_state) =
@ -1311,6 +1312,7 @@ impl App {
| BottomWidgetType::Proc | BottomWidgetType::Proc
| BottomWidgetType::ProcSearch | BottomWidgetType::ProcSearch
| BottomWidgetType::Disk | BottomWidgetType::Disk
| BottomWidgetType::Battery
if self.basic_table_widget_state.is_some() => if self.basic_table_widget_state.is_some() =>
{ {
if let Some(basic_table_widget_state) = if let Some(basic_table_widget_state) =

View File

@ -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 { BottomLayout {
total_row_height_ratio: 3, total_row_height_ratio: 3,
rows: vec![ rows: vec![
@ -573,119 +707,93 @@ impl BottomLayout {
.build(), .build(),
BottomRow::builder() BottomRow::builder()
.canvas_handle_height(true) .canvas_handle_height(true)
.children(vec![ .children(table_widgets)
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(),
])
.build(), .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 { BottomLayout {
total_row_height_ratio: 100, total_row_height_ratio: 100,
rows: vec![ rows: vec![
BottomRow::builder() BottomRow::builder()
.row_height_ratio(30) .row_height_ratio(30)
.children(vec![BottomCol::builder() .total_col_ratio(if use_battery { 3 } else { 1 })
.children(vec![BottomColRow::builder() .children(first_row_layout)
.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()])
.build(), .build(),
BottomRow::builder() BottomRow::builder()
.total_col_ratio(7) .total_col_ratio(7)
@ -907,6 +1015,7 @@ impl BottomWidgetType {
Proc => "Processes", Proc => "Processes",
Temp => "Temperature", Temp => "Temperature",
Disk => "Disks", Disk => "Disks",
Battery => "Battery",
_ => "", _ => "",
} }
} }

View File

@ -350,6 +350,7 @@ impl Painter {
&mut f, &mut f,
app_state, app_state,
rect[0], rect[0],
true,
app_state.current_widget.widget_id, app_state.current_widget.widget_id,
), ),
_ => {} _ => {}
@ -410,6 +411,13 @@ impl Painter {
false, false,
widget_id, widget_id,
), ),
Battery => self.draw_battery_display(
&mut f,
app_state,
vertical_chunks[4],
false,
widget_id,
),
_ => {} _ => {}
} }
} }
@ -541,9 +549,13 @@ impl Painter {
true, true,
widget.widget_id, widget.widget_id,
), ),
Battery => { Battery => self.draw_battery_display(
self.draw_battery_display(f, app_state, *widget_draw_loc, widget.widget_id) f,
} app_state,
*widget_draw_loc,
true,
widget.widget_id,
),
_ => {} _ => {}
} }
} }

View File

@ -23,19 +23,38 @@ impl BasicTableArrows for Painter {
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect,
) { ) {
// Effectively a paragraph with a ton of spacing // Effectively a paragraph with a ton of spacing
let (left_table, right_table) = 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 { app_state
BottomWidgetType::Proc | BottomWidgetType::ProcSearch => { .current_widget
(BottomWidgetType::Temp, BottomWidgetType::Disk) .left_neighbour
} .and_then(|left_widget_id| {
BottomWidgetType::Disk => (BottomWidgetType::Proc, BottomWidgetType::Temp), Some(
BottomWidgetType::Temp => (BottomWidgetType::Disk, BottomWidgetType::Proc), app_state
_ => (BottomWidgetType::Disk, BottomWidgetType::Temp), .widget_map
} .get(&left_widget_id)
} else { .and_then(|left_widget| Some(&left_widget.widget_type))
(BottomWidgetType::Disk, BottomWidgetType::Temp) .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 left_name = left_table.get_pretty_name();
let right_name = right_table.get_pretty_name(); let right_name = right_table.get_pretty_name();
@ -46,12 +65,9 @@ impl BasicTableArrows for Painter {
) as usize; ) as usize;
let arrow_text = vec![ let arrow_text = vec![
Text::Styled( Text::Styled(format!("\n{}", left_name).into(), self.colours.text_style),
format!("\n{}", right_name).into(),
self.colours.text_style,
),
Text::Raw(" ".repeat(num_spaces).into()), 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() let margined_draw_loc = Layout::default()

View File

@ -3,6 +3,7 @@ use std::cmp::max;
use crate::{ use crate::{
app::App, app::App,
canvas::{drawing_utils::calculate_basic_use_bars, Painter}, canvas::{drawing_utils::calculate_basic_use_bars, Painter},
constants::*,
}; };
use tui::{ use tui::{
@ -14,17 +15,20 @@ use tui::{
pub trait BatteryDisplayWidget { pub trait BatteryDisplayWidget {
fn draw_battery_display<B: Backend>( fn draw_battery_display<B: Backend>(
&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 { impl BatteryDisplayWidget for Painter {
fn draw_battery_display<B: Backend>( fn draw_battery_display<B: Backend>(
&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) = if let Some(battery_widget_state) =
app_state.battery_state.widget_states.get_mut(&widget_id) 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 { let title = if app_state.is_expanded {
const TITLE_BASE: &str = " Battery ── Esc to go back "; const TITLE_BASE: &str = " Battery ── Esc to go back ";
let repeat_num = max( let repeat_num = max(
@ -40,21 +44,29 @@ impl BatteryDisplayWidget for Painter {
" Battery ".to_string() " 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 self.colours.highlighted_border_style
} else { } else {
self.colours.border_style self.colours.border_style
}; };
let battery_block = Block::default() let battery_block = if draw_border {
.title(&title) Block::default()
.title_style(if app_state.is_expanded { .title(&title)
border_and_title_style .title_style(if app_state.is_expanded {
} else { border_and_title_style
self.colours.widget_title_style } else {
}) self.colours.widget_title_style
.borders(Borders::ALL) })
.border_style(border_and_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 if let Some(battery_details) = app_state
.canvas_data .canvas_data

View File

@ -94,7 +94,11 @@ impl TempTableWidget for Painter {
let temp_block = if draw_border { let temp_block = if draw_border {
Block::default() Block::default()
.title(&title) .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) .borders(Borders::ALL)
.border_style(border_and_title_style) .border_style(border_and_title_style)
} else if is_on_widget { } else if is_on_widget {

View File

@ -262,7 +262,7 @@ pub fn get_widget_layout(
let bottom_layout = if get_use_basic_mode(matches, config) { let bottom_layout = if get_use_basic_mode(matches, config) {
default_widget_id = DEFAULT_WIDGET_ID; 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 { } else if let Some(rows) = &config.row {
let mut iter_id = 0; // A lazy way of forcing unique IDs *shrugs* let mut iter_id = 0; // A lazy way of forcing unique IDs *shrugs*
let mut total_height_ratio = 0; let mut total_height_ratio = 0;
@ -284,7 +284,7 @@ pub fn get_widget_layout(
total_row_height_ratio: total_height_ratio, 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 { if iter_id > 0 {
ret_bottom_layout.get_movement_mappings(); ret_bottom_layout.get_movement_mappings();
ret_bottom_layout ret_bottom_layout
@ -295,7 +295,7 @@ pub fn get_widget_layout(
} }
} else { } else {
default_widget_id = DEFAULT_WIDGET_ID; 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)) Ok((bottom_layout, default_widget_id))