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

refactor: rewrite column algorithm #227

Merged
merged 12 commits into from
Sep 10, 2020
Prev Previous commit
Next Next commit
Fix grapheme issue with ellipsis generation
  • Loading branch information
ClementTsang committed Sep 10, 2020
commit 3607da92a3100e80a4f940d880640f9a78f64863
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"choco",
"cmdline",
"commandline",
"concat",
"crossterm",
"curr",
"czvf",
Expand Down
16 changes: 10 additions & 6 deletions src/canvas/drawing_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,27 @@ use std::cmp::{max, min};
/// * `soft_widths_max` is the upper limit for a soft width, in percentage of the total width. Use
/// `None` if a hard width goes there.
/// * `soft_widths_desired` is the desired soft width. Use `None` if a hard width goes there.
/// * `spacing_priority` is the order we should prioritize columns in terms of the index. Indices
/// that come earlier in this list go first.
/// * `left_to_right` is a boolean whether to go from left to right if true, or right to left if
/// false.
///
/// **NOTE:** This function ASSUMES THAT ALL PASSED SLICES ARE OF THE SAME SIZE.
///
/// **NOTE:** The returned vector may not be the same size as the slices, this is because including
/// 0-constraints breaks tui-rs.
pub fn get_column_widths(
total_width: u16, hard_widths: &[Option<u16>], soft_widths_min: &[Option<u16>],
soft_widths_max: &[Option<f64>], soft_widths_desired: &[Option<u16>],
spacing_priority: &[usize],
soft_widths_max: &[Option<f64>], soft_widths_desired: &[Option<u16>], left_to_right: bool,
) -> Vec<u16> {
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 spacing_priority {
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);
Expand Down Expand Up @@ -73,7 +77,7 @@ pub fn get_column_widths(

// Redistribute remaining.
while total_width_left > 0 {
for itx in spacing_priority {
for itx in &range {
if column_widths[*itx] > 0 {
column_widths[*itx] += 1;
total_width_left -= 1;
Expand Down
15 changes: 12 additions & 3 deletions src/canvas/widgets/cpu_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ impl CpuGraphWidget for Painter {
.iter()
.map(|width| Some(*width))
.collect::<Vec<_>>()),
&[1, 0],
false,
);
}

Expand All @@ -336,9 +336,18 @@ impl CpuGraphWidget for Painter {
} else {
Cow::Borrowed(&cpu.cpu_name)
};
let truncated_legend: Cow<'_, str> =
if let Some(calculated_column_width) = ccw.get(0) {
if *calculated_column_width == 0 && cpu.legend_value.is_empty() {
Cow::Borrowed("All")
} else {
Cow::Borrowed(&cpu.legend_value)
}
} else {
Cow::Borrowed(&cpu.legend_value)
};

let cpu_string_row: Vec<Cow<'_, str>> =
vec![truncated_name, Cow::Borrowed(&cpu.legend_value)];
let cpu_string_row: Vec<Cow<'_, str>> = vec![truncated_name, truncated_legend];

if cpu_string_row.is_empty() {
offset_scroll_index += 1;
Expand Down
16 changes: 11 additions & 5 deletions src/canvas/widgets/disk_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
constants::*,
};
use std::borrow::Cow;
use unicode_segmentation::UnicodeSegmentation;

const DISK_HEADERS: [&str; 7] = ["Disk", "Mount", "Used", "Free", "Total", "R/s", "W/s"];

Expand Down Expand Up @@ -93,7 +94,7 @@ impl DiskTableWidget for Painter {
.iter()
.map(|w| Some(*w))
.collect::<Vec<_>>()),
&[0, 1, 2, 3, 4, 5, 6],
true,
);
}

Expand All @@ -110,13 +111,18 @@ impl DiskTableWidget for Painter {
if *desired_col_width > *calculated_col_width
&& *calculated_col_width > 0
{
if entry.len() > *calculated_col_width as usize
let graphemes =
UnicodeSegmentation::graphemes(entry.as_str(), true)
.collect::<Vec<&str>>();

if graphemes.len() > *calculated_col_width as usize
&& *calculated_col_width > 1
{
// Truncate with ellipsis
let (first, _last) =
entry.split_at(*calculated_col_width as usize - 1);
Cow::Owned(format!("{}…", first))
let first_n = graphemes
[..(*calculated_col_width as usize - 1)]
.concat();
Cow::Owned(format!("{}…", first_n))
} else {
Cow::Borrowed(entry)
}
Expand Down
2 changes: 1 addition & 1 deletion src/canvas/widgets/network_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ impl NetworkGraphWidget for Painter {
.iter()
.map(|s| Some(*s))
.collect::<Vec<_>>()),
&[0, 1, 2, 3],
true,
);

// Draw
Expand Down
21 changes: 10 additions & 11 deletions src/canvas/widgets/process_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,6 @@ impl ProcessTableWidget for Painter {
vec![None, Some(8), None, None, None, None, None, None, Some(5)]
};

let column_bias = if proc_widget_state.is_grouped {
vec![0, 2, 3, 1, 4, 5, 6, 7]
} else {
vec![0, 2, 3, 1, 4, 5, 6, 7, 8]
};

proc_widget_state.table_width_state.calculated_column_widths =
get_column_widths(
draw_loc.width,
Expand All @@ -325,7 +319,7 @@ impl ProcessTableWidget for Painter {
.iter()
.map(|width| Some(*width))
.collect::<Vec<_>>()),
&column_bias,
true,
);
}

Expand All @@ -342,15 +336,20 @@ impl ProcessTableWidget for Painter {
if *desired_col_width > *calculated_col_width
&& *calculated_col_width > 0
{
let graphemes =
UnicodeSegmentation::graphemes(entry.as_str(), true)
.collect::<Vec<&str>>();

if let Some(alternative) = alternative {
Cow::Borrowed(alternative)
} else if entry.len() > *calculated_col_width as usize
} else if graphemes.len() > *calculated_col_width as usize
&& *calculated_col_width > 1
{
// Truncate with ellipsis
let (first, _last) =
entry.split_at(*calculated_col_width as usize - 1);
Cow::Owned(format!("{}…", first))
let first_n = graphemes
[..(*calculated_col_width as usize - 1)]
.concat();
Cow::Owned(format!("{}…", first_n))
} else {
Cow::Borrowed(entry)
}
Expand Down
16 changes: 11 additions & 5 deletions src/canvas/widgets/temp_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::{
constants::*,
};
use std::borrow::Cow;
use unicode_segmentation::UnicodeSegmentation;

const TEMP_HEADERS: [&str; 2] = ["Sensor", "Temp"];

Expand Down Expand Up @@ -93,7 +94,7 @@ impl TempTableWidget for Painter {
.iter()
.map(|width| Some(*width))
.collect::<Vec<_>>(),
&[1, 0],
false,
);
}

Expand All @@ -110,13 +111,18 @@ impl TempTableWidget for Painter {
if *desired_col_width > *calculated_col_width
&& *calculated_col_width > 0
{
if entry.len() > *calculated_col_width as usize
let graphemes =
UnicodeSegmentation::graphemes(entry.as_str(), true)
.collect::<Vec<&str>>();

if graphemes.len() > *calculated_col_width as usize
&& *calculated_col_width > 1
{
// Truncate with ellipsis
let (first, _last) =
entry.split_at(*calculated_col_width as usize - 1);
Cow::Owned(format!("{}…", first))
let first_n = graphemes
[..(*calculated_col_width as usize - 1)]
.concat();
Cow::Owned(format!("{}…", first_n))
} else {
Cow::Borrowed(entry)
}
Expand Down