summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2022-01-27 16:16:27 -0800
committerGitHub <noreply@github.com>2022-01-27 19:16:27 -0500
commit6c989785fb458a8d7933f98050148e0faf45a8ba (patch)
tree94562a1e352cb7edcb537576c4b60e62117b13b9
parent255b69c15fa3d997737c5e1b51d480c45cb0fe4d (diff)
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.
-rw-r--r--Cargo.toml2
-rw-r--r--src/canvas.rs129
-rw-r--r--src/canvas/drawing_utils.rs192
3 files changed, 191 insertions, 132 deletions
diff --git a/Cargo.toml b/Cargo.toml
index eb0f399f..9d56e94e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@ path = "src/bin/main.rs"
doc = false
[lib]
-test = false
+test = true
doctest = false
doc = false
diff --git a/src/canvas.rs b/src/canvas.rs
index 4648a417..447d9421 100644
--- a/src/canvas.rs
+++ b/src/canvas.rs
@@ -282,9 +282,6 @@ impl Painter {
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) {
f.render_widget(
Paragraph::new(Span::styled(
@@ -559,44 +556,62 @@ impl Painter {
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.split(vertical_chunks[1]);
- self.draw_basic_cpu(f, app_state, vertical_chunks[0], 1);
- self.draw_basic_memory(f, app_state, middle_chunks[0], 2);
- self.draw_basic_network(f, app_state, middle_chunks[1], 3);
+
+ if vertical_chunks[0].width >= 2 {
+ 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);
+ }
+ if middle_chunks[1].width >= 2 {
+ self.draw_basic_network(f, app_state, middle_chunks[1], 3);
+ }
let mut later_widget_id: Option<u64> = None;
if let Some(basic_table_widget_state) = &app_state.basic_table_widget_state {
let widget_id = basic_table_widget_state.currently_displayed_widget_id;
later_widget_id = Some(widget_id);
- match basic_table_widget_state.currently_displayed_widget_type {
- Disk => {
- self.draw_disk_table(f, app_state, vertical_chunks[3], false, widget_id)
- }
- Proc | ProcSort => {
- let wid = widget_id
- - match basic_table_widget_state.currently_displayed_widget_type {
- ProcSearch => 1,
- ProcSort => 2,
- _ => 0,
- };
- self.draw_process_features(
+ if vertical_chunks[3].width >= 2 {
+ match basic_table_widget_state.currently_displayed_widget_type {
+ Disk => self.draw_disk_table(
f,
app_state,
vertical_chunks[3],
false,
- wid,
- );
- }
- Temp => {
- self.draw_temp_table(f, app_state, vertical_chunks[3], false, widget_id)
+ widget_id,
+ ),
+ Proc | ProcSort => {
+ let wid = widget_id
+ - match basic_table_widget_state.currently_displayed_widget_type
+ {
+ ProcSearch => 1,
+ ProcSort => 2,
+ _ => 0,
+ };
+ self.draw_process_features(
+ f,
+ app_state,
+ vertical_chunks[3],
+ false,
+ wid,
+ );
+ }
+ Temp => self.draw_temp_table(
+ f,
+ app_state,
+ vertical_chunks[3],
+ false,
+ widget_id,
+ ),
+ Battery => self.draw_battery_display(
+ f,
+ app_state,
+ vertical_chunks[3],
+ false,
+ widget_id,
+ ),
+ _ => {}
}
- Battery => self.draw_battery_display(
- f,
- app_state,
- vertical_chunks[3],
- false,
- widget_id,
- ),
- _ => {}
}
}
@@ -712,32 +727,34 @@ impl Painter {
) {
use BottomWidgetType::*;
for (widget, widget_draw_loc) in widgets.children.iter().zip(widget_draw_locs) {
- match &widget.widget_type {
- Empty => {}
- Cpu => self.draw_cpu(f, app_state, *widget_draw_loc, widget.widget_id),
- Mem => self.draw_memory_graph(f, app_state, *widget_draw_loc, widget.widget_id),
- Net => self.draw_network(f, app_state, *widget_draw_loc, widget.widget_id),
- Temp => {
- self.draw_temp_table(f, app_state, *widget_draw_loc, true, widget.widget_id)
- }
- Disk => {
- self.draw_disk_table(f, app_state, *widget_draw_loc, true, widget.widget_id)
+ if widget_draw_loc.width >= 2 && widget_draw_loc.height >= 2 {
+ match &widget.widget_type {
+ Empty => {}
+ Cpu => self.draw_cpu(f, app_state, *widget_draw_loc, widget.widget_id),
+ Mem => self.draw_memory_graph(f, app_state, *widget_draw_loc, widget.widget_id),
+ Net => self.draw_network(f, app_state, *widget_draw_loc, widget.widget_id),
+ Temp => {
+ self.draw_temp_table(f, app_state, *widget_draw_loc, true, widget.widget_id)
+ }
+ Disk => {
+ self.draw_disk_table(f, app_state, *widget_draw_loc, true, widget.widget_id)
+ }
+ Proc => self.draw_process_features(
+ f,
+ app_state,
+ *widget_draw_loc,
+ true,
+ widget.widget_id,
+ ),
+ Battery => self.draw_battery_display(
+ f,
+ app_state,
+ *widget_draw_loc,
+ true,
+ widget.widget_id,
+ ),
+ _ => {}
}
- Proc => self.draw_process_features(
- f,
- app_state,
- *widget_draw_loc,
- true,
- widget.widget_id,
- ),
- Battery => self.draw_battery_display(
- f,
- app_state,
- *widget_draw_loc,
- true,
- widget.widget_id,
- ),
- _ => {}
}
}
}
diff --git a/src/canvas/drawing_utils.rs b/src/canvas/drawing_utils.rs
index ee81127a..129a80a9 100644
--- a/src/canvas/drawing_utils.rs
+++ b/src/canvas/drawing_utils.rs
@@ -35,93 +35,82 @@ pub fn get_column_widths(
"soft width max length != soft width desired length!"
);
- let initial_width = total_width - 2;
- let mut total_width_left = initial_width;
- let mut column_widths: Vec<u16> = vec![0; hard_widths.len()];
- let range: Vec<usize> = if left_to_right {
- (0..hard_widths.len()).collect()
- } else {
- (0..hard_widths.len()).rev().collect()
- };
-
- for itx in &range {
- if let Some(Some(hard_width)) = hard_widths.get(*itx) {
- // Hard width...
- let space_taken = min(*hard_width, total_width_left);
+ if total_width > 2 {
+ let initial_width = total_width - 2;
+ let mut total_width_left = initial_width;
+ let mut column_widths: Vec<u16> = vec![0; hard_widths.len()];
+ let range: Vec<usize> = if left_to_right {
+ (0..hard_widths.len()).collect()
+ } else {
+ (0..hard_widths.len()).rev().collect()
+ };
- // TODO [COLUMN MOVEMENT]: Remove this
- if *hard_width > space_taken {
- break;
- }
+ for itx in &range {
+ if let Some(Some(hard_width)) = hard_widths.get(*itx) {
+ // Hard width...
+ let space_taken = min(*hard_width, total_width_left);
- column_widths[*itx] = space_taken;
- total_width_left -= space_taken;
- total_width_left = total_width_left.saturating_sub(1);
- } else if let (
- Some(Some(soft_width_max)),
- Some(Some(soft_width_min)),
- Some(Some(soft_width_desired)),
- ) = (
- soft_widths_max.get(*itx),
- soft_widths_min.get(*itx),
- soft_widths_desired.get(*itx),
- ) {
- // Soft width...
- let soft_limit = max(
- if soft_width_max.is_sign_negative() {
- *soft_width_desired
- } else {
- (*soft_width_max * initial_width as f64).ceil() as u16
- },
- *soft_width_min,
- );
- let space_taken = min(min(soft_limit, *soft_width_desired), total_width_left);
-
- // TODO [COLUMN MOVEMENT]: Remove this
- if *soft_width_min > space_taken {
- break;
- }
+ // TODO [COLUMN MOVEMENT]: Remove this
+ if *hard_width > space_taken {
+ break;
+ }
- column_widths[*itx] = space_taken;
- total_width_left -= space_taken;
- total_width_left = total_width_left.saturating_sub(1);
- }
- }
+ column_widths[*itx] = space_taken;
+ total_width_left -= space_taken;
+ total_width_left = total_width_left.saturating_sub(1);
+ } else if let (
+ Some(Some(soft_width_max)),
+ Some(Some(soft_width_min)),
+ Some(Some(soft_width_desired)),
+ ) = (
+ soft_widths_max.get(*itx),
+ soft_widths_min.get(*itx),
+ soft_widths_desired.get(*itx),
+ ) {
+ // Soft width...
+ let soft_limit = max(
+ if soft_width_max.is_sign_negative() {
+ *soft_width_desired
+ } else {
+ (*soft_width_max * initial_width as f64).ceil() as u16
+ },
+ *soft_width_min,
+ );
+ let space_taken = min(min(soft_limit, *soft_width_desired), total_width_left);
- // Redistribute remaining.
- while total_width_left > 0 {
- for itx in &range {
- if column_widths[*itx] > 0 {
- column_widths[*itx] += 1;
- total_width_left -= 1;
- if total_width_left == 0 {
+ // TODO [COLUMN MOVEMENT]: Remove this
+ if *soft_width_min > space_taken {
break;
}
+
+ column_widths[*itx] = space_taken;
+ total_width_left -= space_taken;
+ total_width_left = total_width_left.saturating_sub(1);
}
}
- }
- 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);
+ while let Some(0) = column_widths.last() {
+ column_widths.pop();
+ }
+
+ if !column_widths.is_empty() {
+ // Redistribute remaining.
+ let amount_per_slot = total_width_left / column_widths.len() as u16;
+ total_width_left %= column_widths.len() as u16;
+ for (index, width) in column_widths.iter_mut().enumerate() {
+ if (index as u16) < total_width_left {
+ *width += amount_per_slot + 1;
+ } else {
+ *width += amount_per_slot;
+ }
}
- } else {
- filtered_column_widths.push(*width);
}
- });
- 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
-/// shoving information as far right as required.
-// pub fn greedy_get_column_widths() -> Vec<u16> {
-// vec![]
-// }
+ column_widths
+ } else {
+ vec![]
+ }
+}
pub fn get_search_start_position(
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)
}
+
+#[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"
+ );
+ }
+}