mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-31 01:24:31 +02:00
bug: fix issues caused by having a width that is too small (#665)
Due to a missing check, you could resize the window to a width that was too small, and it would trigger an endless while-loop for any table while trying to redistribute remaining space. This has been rectified with an explicit check, as well as a smarter method of redistributing remaining space borrowed from the rewrite. This also adds explicit width checks for widgets that have borders; if the width is <2, before, it would panic. Note that the rewrite I have kinda fixes all these issues already, so I don't want to invest too hard into this, but this should be fine as a patch for now. Also note that minimal heights don't seem to be causing any issues, it just seems to be minimal widths.
This commit is contained in:
parent
255b69c15f
commit
6c989785fb
@ -19,7 +19,7 @@ path = "src/bin/main.rs"
|
|||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
test = false
|
test = true
|
||||||
doctest = false
|
doctest = false
|
||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
|
@ -282,9 +282,6 @@ impl Painter {
|
|||||||
self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
|
self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: [CONFIG] write this, should call painter init and any changed colour functions...
|
|
||||||
pub fn update_painter_colours(&mut self) {}
|
|
||||||
|
|
||||||
fn draw_frozen_indicator<B: Backend>(&self, f: &mut Frame<'_, B>, draw_loc: Rect) {
|
fn draw_frozen_indicator<B: Backend>(&self, f: &mut Frame<'_, B>, draw_loc: Rect) {
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
Paragraph::new(Span::styled(
|
Paragraph::new(Span::styled(
|
||||||
@ -559,21 +556,34 @@ impl Painter {
|
|||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
|
||||||
.split(vertical_chunks[1]);
|
.split(vertical_chunks[1]);
|
||||||
|
|
||||||
|
if vertical_chunks[0].width >= 2 {
|
||||||
self.draw_basic_cpu(f, app_state, vertical_chunks[0], 1);
|
self.draw_basic_cpu(f, app_state, vertical_chunks[0], 1);
|
||||||
|
}
|
||||||
|
if middle_chunks[0].width >= 2 {
|
||||||
self.draw_basic_memory(f, app_state, middle_chunks[0], 2);
|
self.draw_basic_memory(f, app_state, middle_chunks[0], 2);
|
||||||
|
}
|
||||||
|
if middle_chunks[1].width >= 2 {
|
||||||
self.draw_basic_network(f, app_state, middle_chunks[1], 3);
|
self.draw_basic_network(f, app_state, middle_chunks[1], 3);
|
||||||
|
}
|
||||||
|
|
||||||
let mut later_widget_id: Option<u64> = None;
|
let mut later_widget_id: Option<u64> = None;
|
||||||
if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state {
|
if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state {
|
||||||
let widget_id = basic_table_widget_state.currently_displayed_widget_id;
|
let widget_id = basic_table_widget_state.currently_displayed_widget_id;
|
||||||
later_widget_id = Some(widget_id);
|
later_widget_id = Some(widget_id);
|
||||||
|
if vertical_chunks[3].width >= 2 {
|
||||||
match basic_table_widget_state.currently_displayed_widget_type {
|
match basic_table_widget_state.currently_displayed_widget_type {
|
||||||
Disk => {
|
Disk => self.draw_disk_table(
|
||||||
self.draw_disk_table(f, app_state, vertical_chunks[3], false, widget_id)
|
f,
|
||||||
}
|
app_state,
|
||||||
|
vertical_chunks[3],
|
||||||
|
false,
|
||||||
|
widget_id,
|
||||||
|
),
|
||||||
Proc | ProcSort => {
|
Proc | ProcSort => {
|
||||||
let wid = widget_id
|
let wid = widget_id
|
||||||
- match basic_table_widget_state.currently_displayed_widget_type {
|
- match basic_table_widget_state.currently_displayed_widget_type
|
||||||
|
{
|
||||||
ProcSearch => 1,
|
ProcSearch => 1,
|
||||||
ProcSort => 2,
|
ProcSort => 2,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
@ -586,9 +596,13 @@ impl Painter {
|
|||||||
wid,
|
wid,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Temp => {
|
Temp => self.draw_temp_table(
|
||||||
self.draw_temp_table(f, app_state, vertical_chunks[3], false, widget_id)
|
f,
|
||||||
}
|
app_state,
|
||||||
|
vertical_chunks[3],
|
||||||
|
false,
|
||||||
|
widget_id,
|
||||||
|
),
|
||||||
Battery => self.draw_battery_display(
|
Battery => self.draw_battery_display(
|
||||||
f,
|
f,
|
||||||
app_state,
|
app_state,
|
||||||
@ -599,6 +613,7 @@ impl Painter {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(widget_id) = later_widget_id {
|
if let Some(widget_id) = later_widget_id {
|
||||||
self.draw_basic_table_arrows(f, app_state, vertical_chunks[2], widget_id);
|
self.draw_basic_table_arrows(f, app_state, vertical_chunks[2], widget_id);
|
||||||
@ -712,6 +727,7 @@ impl Painter {
|
|||||||
) {
|
) {
|
||||||
use BottomWidgetType::*;
|
use BottomWidgetType::*;
|
||||||
for (widget, widget_draw_loc) in widgets.children.iter().zip(widget_draw_locs) {
|
for (widget, widget_draw_loc) in widgets.children.iter().zip(widget_draw_locs) {
|
||||||
|
if widget_draw_loc.width >= 2 && widget_draw_loc.height >= 2 {
|
||||||
match &widget.widget_type {
|
match &widget.widget_type {
|
||||||
Empty => {}
|
Empty => {}
|
||||||
Cpu => self.draw_cpu(f, app_state, *widget_draw_loc, widget.widget_id),
|
Cpu => self.draw_cpu(f, app_state, *widget_draw_loc, widget.widget_id),
|
||||||
@ -742,3 +758,4 @@ impl Painter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ pub fn get_column_widths(
|
|||||||
"soft width max length != soft width desired length!"
|
"soft width max length != soft width desired length!"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if total_width > 2 {
|
||||||
let initial_width = total_width - 2;
|
let initial_width = total_width - 2;
|
||||||
let mut total_width_left = initial_width;
|
let mut total_width_left = initial_width;
|
||||||
let mut column_widths: Vec<u16> = vec![0; hard_widths.len()];
|
let mut column_widths: Vec<u16> = vec![0; hard_widths.len()];
|
||||||
@ -88,40 +89,28 @@ pub fn get_column_widths(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Some(0) = column_widths.last() {
|
||||||
|
column_widths.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !column_widths.is_empty() {
|
||||||
// Redistribute remaining.
|
// Redistribute remaining.
|
||||||
while total_width_left > 0 {
|
let amount_per_slot = total_width_left / column_widths.len() as u16;
|
||||||
for itx in &range {
|
total_width_left %= column_widths.len() as u16;
|
||||||
if column_widths[*itx] > 0 {
|
for (index, width) in column_widths.iter_mut().enumerate() {
|
||||||
column_widths[*itx] += 1;
|
if (index as u16) < total_width_left {
|
||||||
total_width_left -= 1;
|
*width += amount_per_slot + 1;
|
||||||
if total_width_left == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut filtered_column_widths: Vec<u16> = vec![];
|
|
||||||
let mut still_seeing_zeros = true;
|
|
||||||
column_widths.iter().rev().for_each(|width| {
|
|
||||||
if still_seeing_zeros {
|
|
||||||
if *width != 0 {
|
|
||||||
still_seeing_zeros = false;
|
|
||||||
filtered_column_widths.push(*width);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
filtered_column_widths.push(*width);
|
*width += amount_per_slot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
filtered_column_widths.reverse();
|
|
||||||
filtered_column_widths
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME: [command move] This is a greedy method of determining column widths. This is reserved for columns where we are okay with
|
column_widths
|
||||||
/// shoving information as far right as required.
|
} else {
|
||||||
// pub fn greedy_get_column_widths() -> Vec<u16> {
|
vec![]
|
||||||
// vec![]
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn get_search_start_position(
|
pub fn get_search_start_position(
|
||||||
num_columns: usize, cursor_direction: &app::CursorDirection, cursor_bar: &mut usize,
|
num_columns: usize, cursor_direction: &app::CursorDirection, cursor_bar: &mut usize,
|
||||||
@ -216,3 +205,56 @@ pub fn interpolate_points(point_one: &(f64, f64), point_two: &(f64, f64), time:
|
|||||||
|
|
||||||
(point_one.1 + (time - point_one.0) * slope).max(0.0)
|
(point_one.1 + (time - point_one.0) * slope).max(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_zero_width() {
|
||||||
|
assert_eq!(
|
||||||
|
get_column_widths(
|
||||||
|
0,
|
||||||
|
&[Some(1), None, None],
|
||||||
|
&[None, Some(1), Some(2)],
|
||||||
|
&[None, Some(0.125), Some(0.5)],
|
||||||
|
&[None, Some(10), Some(10)],
|
||||||
|
true
|
||||||
|
),
|
||||||
|
vec![],
|
||||||
|
"vector should be empty"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_two_width() {
|
||||||
|
assert_eq!(
|
||||||
|
get_column_widths(
|
||||||
|
2,
|
||||||
|
&[Some(1), None, None],
|
||||||
|
&[None, Some(1), Some(2)],
|
||||||
|
&[None, Some(0.125), Some(0.5)],
|
||||||
|
&[None, Some(10), Some(10)],
|
||||||
|
true
|
||||||
|
),
|
||||||
|
vec![],
|
||||||
|
"vector should be empty"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_non_zero_width() {
|
||||||
|
assert_eq!(
|
||||||
|
get_column_widths(
|
||||||
|
16,
|
||||||
|
&[Some(1), None, None],
|
||||||
|
&[None, Some(1), Some(2)],
|
||||||
|
&[None, Some(0.125), Some(0.5)],
|
||||||
|
&[None, Some(10), Some(10)],
|
||||||
|
true
|
||||||
|
),
|
||||||
|
vec![2, 2, 7],
|
||||||
|
"vector should not be empty"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user