Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: fix issues caused by having a width that is too small #665

Merged
merged 4 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ path = "src/bin/main.rs"
doc = false

[lib]
test = false
test = true
doctest = false
doc = false

Expand Down
129 changes: 73 additions & 56 deletions src/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
),
_ => {}
}
}

Expand Down Expand Up @@ -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,
),
_ => {}
}
}
}
Expand Down
192 changes: 117 additions & 75 deletions src/canvas/drawing_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
);
}
}