diff --git a/CHANGELOG.md b/CHANGELOG.md index 71c522cb..916d77cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#1230](https://github.com/ClementTsang/bottom/pull/1230): Fix core dump if the terminal is closed while bottom is open. +## Changes + +- [#1236](https://github.com/ClementTsang/bottom/pull/1236): Hide the battery tab selector if there is only one battery detected. + ## [0.9.3] - 2023-06-25 ## Bug Fixes diff --git a/src/app.rs b/src/app.rs index 03782a56..468eeed8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -693,7 +693,7 @@ impl App { } } BottomWidgetType::Battery => { - if !self.converted_data.battery_data.is_empty() { + if self.converted_data.battery_data.len() > 1 { if let Some(battery_widget_state) = self .states .battery_state @@ -754,7 +754,7 @@ impl App { } } BottomWidgetType::Battery => { - if !self.converted_data.battery_data.is_empty() { + if self.converted_data.battery_data.len() > 1 { let battery_count = self.converted_data.battery_data.len(); if let Some(battery_widget_state) = self .states diff --git a/src/canvas/widgets/battery_display.rs b/src/canvas/widgets/battery_display.rs index 5e579a9c..662557aa 100644 --- a/src/canvas/widgets/battery_display.rs +++ b/src/canvas/widgets/battery_display.rs @@ -6,6 +6,7 @@ use tui::{ widgets::{Block, Borders, Cell, Paragraph, Row, Table, Tabs}, }; use unicode_segmentation::UnicodeSegmentation; +use unicode_width::UnicodeWidthStr; use crate::{ app::App, @@ -69,36 +70,55 @@ impl Painter { Block::default().borders(Borders::NONE) }; - let battery_names = app_state - .converted_data - .battery_data - .iter() - .map(|battery| &battery.battery_name) - .collect::>(); + if app_state.converted_data.battery_data.len() > 1 { + let battery_names = app_state + .converted_data + .battery_data + .iter() + .enumerate() + .map(|(itx, _)| format!("Battery {itx}")) + .collect::>(); - let tab_draw_loc = Layout::default() - .constraints([ - Constraint::Length(1), - Constraint::Length(2), - Constraint::Min(0), - ]) - .direction(Direction::Vertical) - .split(draw_loc)[1]; + let tab_draw_loc = Layout::default() + .constraints([ + Constraint::Length(1), + Constraint::Length(2), + Constraint::Min(0), + ]) + .direction(Direction::Vertical) + .split(draw_loc)[1]; - f.render_widget( - Tabs::new( - battery_names - .iter() - .map(|name| Line::from((*name).clone())) - .collect::>(), - ) - .block(Block::default()) - .divider(tui::symbols::line::VERTICAL) - .style(self.colours.text_style) - .highlight_style(self.colours.currently_selected_text_style) - .select(battery_widget_state.currently_selected_battery_index), - tab_draw_loc, - ); + f.render_widget( + Tabs::new( + battery_names + .iter() + .map(|name| Line::from((*name).clone())) + .collect::>(), + ) + .divider(tui::symbols::line::VERTICAL) + .style(self.colours.text_style) + .highlight_style(self.colours.currently_selected_text_style) + .select(battery_widget_state.currently_selected_battery_index), + tab_draw_loc, + ); + + if should_get_widget_bounds { + let mut current_x = tab_draw_loc.x; + let current_y = tab_draw_loc.y; + let mut tab_click_locs: Vec<((u16, u16), (u16, u16))> = vec![]; + for battery in battery_names { + // +1 because there's a space after the tab label. + let width = UnicodeWidthStr::width(battery.as_str()) as u16; + tab_click_locs + .push(((current_x, current_y), (current_x + width, current_y))); + + // +4 because we want to go one space, then one space past to get to the '|', then 2 more + // to start at the blank space before the tab label. + current_x += width + 4; + } + battery_widget_state.tab_click_locs = Some(tab_click_locs); + } + } let margined_draw_loc = Layout::default() .constraints([Constraint::Percentage(100)]) @@ -183,28 +203,28 @@ impl Painter { Row::new(["State", &battery_details.state]).style(self.colours.text_style), ); - let mut s: String; // Keep string in scope. + let mut time: String; // Keep string lifetime in scope. { let style = self.colours.text_style; match &battery_details.battery_duration { BatteryDuration::ToEmpty(secs) => { - s = long_time(*secs); + time = long_time(*secs); - if half_width as usize > s.len() { - battery_rows.push(Row::new(["Time to empty", &s]).style(style)); + if half_width as usize > time.len() { + battery_rows.push(Row::new(["Time to empty", &time]).style(style)); } else { - s = short_time(*secs); - battery_rows.push(Row::new(["To empty", &s]).style(style)); + time = short_time(*secs); + battery_rows.push(Row::new(["To empty", &time]).style(style)); } } BatteryDuration::ToFull(secs) => { - s = long_time(*secs); + time = long_time(*secs); - if half_width as usize > s.len() { - battery_rows.push(Row::new(["Time to full", &s]).style(style)); + if half_width as usize > time.len() { + battery_rows.push(Row::new(["Time to full", &time]).style(style)); } else { - s = short_time(*secs); - battery_rows.push(Row::new(["To full", &s]).style(style)); + time = short_time(*secs); + battery_rows.push(Row::new(["To full", &time]).style(style)); } } BatteryDuration::Empty @@ -217,11 +237,17 @@ impl Painter { Row::new(["Health %", &battery_details.health]).style(self.colours.text_style), ); + let header = if app_state.converted_data.battery_data.len() > 1 { + Row::new([""]).bottom_margin(table_gap) + } else { + Row::default() + }; + // Draw f.render_widget( Table::new(battery_rows) .block(battery_block) - .header(Row::new([""]).bottom_margin(table_gap)) + .header(header) .widths(&[Constraint::Percentage(50), Constraint::Percentage(50)]), margined_draw_loc, ); @@ -240,24 +266,6 @@ impl Painter { } if should_get_widget_bounds { - // Tab wizardry - if !battery_names.is_empty() { - let mut current_x = tab_draw_loc.x; - let current_y = tab_draw_loc.y; - let mut tab_click_locs: Vec<((u16, u16), (u16, u16))> = vec![]; - for battery in battery_names { - // +1 because there's a space after the tab label. - let width = unicode_width::UnicodeWidthStr::width(battery.as_str()) as u16; - tab_click_locs - .push(((current_x, current_y), (current_x + width, current_y))); - - // +4 because we want to go one space, then one space past to get to the '|', then 2 more - // to start at the blank space before the tab label. - current_x += width + 4; - } - battery_widget_state.tab_click_locs = Some(tab_click_locs); - } - // Update draw loc in widget map if let Some(widget) = app_state.widget_map.get_mut(&widget_id) { widget.top_left_corner = Some((margined_draw_loc.x, margined_draw_loc.y)); diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 59ffcdce..0bbe9eb3 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -26,7 +26,6 @@ pub enum BatteryDuration { #[derive(Default, Debug)] pub struct ConvertedBatteryData { - pub battery_name: String, pub charge_percentage: f64, pub watt_consumption: String, pub battery_duration: BatteryDuration, @@ -520,9 +519,7 @@ pub fn convert_battery_harvest(current_data: &DataCollection) -> Vec