Column width layout fix

This commit is contained in:
ClementTsang 2021-12-31 01:42:11 -05:00
parent f45b65e68e
commit 863ae0059a
6 changed files with 133 additions and 29 deletions

View File

@ -11,6 +11,7 @@ use std::borrow::Cow;
pub struct ConvertedData<'a> {
data: &'a DataCollection,
temp_table: Option<Vec<Vec<Cow<'static, str>>>>,
disk_table: Option<Vec<Vec<Cow<'static, str>>>>,
}
impl<'a> ConvertedData<'a> {
@ -18,6 +19,7 @@ impl<'a> ConvertedData<'a> {
Self {
data,
temp_table: None,
disk_table: None,
}
}
@ -52,6 +54,64 @@ impl<'a> ConvertedData<'a> {
}
}
}
pub fn disk_table(&mut self) -> Vec<Vec<Cow<'static, str>>> {
match &self.disk_table {
Some(disk_table) => disk_table.clone(),
None => {
if self.data.disk_harvest.is_empty() {
vec![vec!["No Disks Found".into(), "".into()]]
} else {
self.data
.disk_harvest
.iter()
.zip(&self.data.io_labels)
.map(|(disk, (io_read, io_write))| {
let free_space_fmt = if let Some(free_space) = disk.free_space {
let converted_free_space = get_decimal_bytes(free_space);
Cow::Owned(format!(
"{:.*}{}",
0, converted_free_space.0, converted_free_space.1
))
} else {
"N/A".into()
};
let total_space_fmt = if let Some(total_space) = disk.total_space {
let converted_total_space = get_decimal_bytes(total_space);
Cow::Owned(format!(
"{:.*}{}",
0, converted_total_space.0, converted_total_space.1
))
} else {
"N/A".into()
};
let usage_fmt = if let (Some(used_space), Some(total_space)) =
(disk.used_space, disk.total_space)
{
Cow::Owned(format!(
"{:.0}%",
used_space as f64 / total_space as f64 * 100_f64
))
} else {
"N/A".into()
};
vec![
disk.name.clone().into(),
disk.mount_point.clone().into(),
usage_fmt,
free_space_fmt,
total_space_fmt,
io_read.clone().into(),
io_write.clone().into(),
]
})
.collect::<Vec<_>>()
}
}
}
}
}
/// Point is of time, data

View File

@ -18,3 +18,6 @@ pub use container::Container;
pub mod empty;
pub use empty::Empty;
pub mod padding;
pub use padding::*;

View File

View File

@ -71,31 +71,36 @@ impl<Message> TextTable<Message> {
.columns
.iter()
.map(|column| {
let desired = column.name.graphemes(true).count() as u16; // FIXME: Should this be +1 if sorting is enabled?
let width = match column.width_constraint {
TextColumnConstraint::Fill => {
let desired = column.name.graphemes(true).count().saturating_add(1) as u16;
min(desired, width_remaining)
}
TextColumnConstraint::Fill => min(desired, width_remaining),
TextColumnConstraint::Length(length) => min(length, width_remaining),
TextColumnConstraint::Percentage(percentage) => {
let length = total_width * percentage / 100;
min(length, width_remaining)
}
TextColumnConstraint::MaxLength(length) => {
let desired = column.name.graphemes(true).count().saturating_add(1) as u16;
min(min(length, desired), width_remaining)
}
TextColumnConstraint::MaxLength(length) => min(length, width_remaining),
TextColumnConstraint::MaxPercentage(percentage) => {
let desired = column.name.graphemes(true).count().saturating_add(1) as u16;
let length = total_width * percentage / 100;
min(min(desired, length), width_remaining)
min(length, width_remaining)
}
};
width_remaining -= width;
width
if desired > width {
0
} else {
// +1 for the spacing
width_remaining -= width + 1;
width
}
})
.collect();
// Prune from the end
while let Some(0) = column_widths.last() {
column_widths.pop();
}
if !column_widths.is_empty() {
let amount_per_slot = width_remaining / column_widths.len() as u16;
width_remaining %= column_widths.len() as u16;

View File

@ -1,30 +1,66 @@
use tui::{text::Text, widgets::Paragraph, Frame};
use crate::{
app::AppConfig,
canvas::Painter,
data_conversion::ConvertedData,
tuine::{
Bounds, DrawContext, LayoutNode, SimpleTable, Size, StateContext, Status, TmpComponent,
ViewContext,
},
};
use crate::tuine::{DrawContext, StateContext, TmpComponent};
use super::{simple_table, AppWidget};
/// A [`DiskTable`] is a table displaying disk data.
pub struct DiskTable {}
/// A [`DiskTable`] is a table displaying temperature data.
///
/// It wraps a [`SimpleTable`], with set columns and manages extracting data and styling.
pub struct DiskTable<Message> {
inner: SimpleTable<Message>,
}
impl super::AppWidget for DiskTable {
impl<Message> DiskTable<Message> {}
impl<Message> AppWidget for DiskTable<Message> {
fn build(
ctx: &mut crate::tuine::ViewContext<'_>, painter: &crate::canvas::Painter,
config: &crate::app::AppConfig, data: &mut crate::data_conversion::ConvertedData<'_>,
ctx: &mut ViewContext<'_>, painter: &Painter, config: &AppConfig,
data: &mut ConvertedData<'_>,
) -> Self {
Self {}
let style = simple_table::StyleSheet {
text: painter.colours.text_style,
selected_text: painter.colours.currently_selected_text_style,
table_header: painter.colours.table_header_style,
border: painter.colours.border_style,
};
let rows = data.disk_table();
Self {
inner: SimpleTable::build(
ctx,
style,
vec!["Disk", "Mount", "Used", "Free", "Total", "R/s", "W/s"],
rows,
),
}
}
}
impl<Message> TmpComponent<Message> for DiskTable {
impl<Message> TmpComponent<Message> for DiskTable<Message> {
fn draw<Backend>(
&mut self, _state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
frame: &mut Frame<'_, Backend>,
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
frame: &mut tui::Frame<'_, Backend>,
) where
Backend: tui::backend::Backend,
{
let rect = draw_ctx.global_rect();
frame.render_widget(
Paragraph::new(Text::raw("Disk Table")).block(tui::widgets::Block::default()),
rect,
);
self.inner.draw(state_ctx, draw_ctx, frame);
}
fn on_event(
&mut self, state_ctx: &mut StateContext<'_>, draw_ctx: &DrawContext<'_>,
event: crate::tuine::Event, messages: &mut Vec<Message>,
) -> Status {
self.inner.on_event(state_ctx, draw_ctx, event, messages)
}
fn layout(&self, bounds: Bounds, node: &mut LayoutNode) -> Size {
self.inner.layout(bounds, node)
}
}

View File

@ -19,7 +19,7 @@ where
BatteryTable(BatteryTable),
CpuGraph(CpuGraph),
CpuSimple(CpuSimple),
DiskTable(DiskTable),
DiskTable(DiskTable<Message>),
MemGraph(MemGraph),
MemSimple(MemSimple),
NetGraph(NetGraph),