summaryrefslogtreecommitdiffstats
path: root/src/app/widgets/disk_table.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/widgets/disk_table.rs')
-rw-r--r--src/app/widgets/disk_table.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/app/widgets/disk_table.rs b/src/app/widgets/disk_table.rs
new file mode 100644
index 00000000..be444b45
--- /dev/null
+++ b/src/app/widgets/disk_table.rs
@@ -0,0 +1,147 @@
+use std::{borrow::Cow, cmp::max};
+
+use kstring::KString;
+use tui::text::Text;
+
+use crate::{
+ app::AppConfigFields,
+ canvas::canvas_colours::CanvasColours,
+ components::data_table::{
+ Column, ColumnHeader, DataTable, DataTableColumn, DataTableProps, DataTableStyling,
+ DataToCell,
+ },
+ utils::gen_util::{get_decimal_bytes, truncate_text},
+};
+
+#[derive(Clone)]
+pub struct DiskWidgetData {
+ pub name: KString,
+ pub mount_point: KString,
+ pub free_bytes: Option<u64>,
+ pub used_bytes: Option<u64>,
+ pub total_bytes: Option<u64>,
+ pub io_read: KString,
+ pub io_write: KString,
+}
+
+impl DiskWidgetData {
+ pub fn free_space(&self) -> KString {
+ if let Some(free_bytes) = self.free_bytes {
+ let converted_free_space = get_decimal_bytes(free_bytes);
+ format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1).into()
+ } else {
+ "N/A".into()
+ }
+ }
+
+ pub fn total_space(&self) -> KString {
+ if let Some(total_bytes) = self.total_bytes {
+ let converted_total_space = get_decimal_bytes(total_bytes);
+ format!(
+ "{:.*}{}",
+ 0, converted_total_space.0, converted_total_space.1
+ )
+ .into()
+ } else {
+ "N/A".into()
+ }
+ }
+
+ pub fn usage(&self) -> KString {
+ if let (Some(used_bytes), Some(total_bytes)) = (self.used_bytes, self.total_bytes) {
+ format!("{:.0}%", used_bytes as f64 / total_bytes as f64 * 100_f64).into()
+ } else {
+ "N/A".into()
+ }
+ }
+}
+
+pub enum DiskWidgetColumn {
+ Disk,
+ Mount,
+ Used,
+ Free,
+ Total,
+ IoRead,
+ IoWrite,
+}
+
+impl ColumnHeader for DiskWidgetColumn {
+ fn text(&self) -> Cow<'static, str> {
+ match self {
+ DiskWidgetColumn::Disk => "Disk",
+ DiskWidgetColumn::Mount => "Mount",
+ DiskWidgetColumn::Used => "Used",
+ DiskWidgetColumn::Free => "Free",
+ DiskWidgetColumn::Total => "Total",
+ DiskWidgetColumn::IoRead => "R/s",
+ DiskWidgetColumn::IoWrite => "W/s",
+ }
+ .into()
+ }
+}
+
+impl DataToCell<DiskWidgetColumn> for DiskWidgetData {
+ fn to_cell<'a>(&'a self, column: &DiskWidgetColumn, calculated_width: u16) -> Option<Text<'a>> {
+ let text = match column {
+ DiskWidgetColumn::Disk => truncate_text(&self.name, calculated_width),
+ DiskWidgetColumn::Mount => truncate_text(&self.mount_point, calculated_width),
+ DiskWidgetColumn::Used => truncate_text(&self.usage(), calculated_width),
+ DiskWidgetColumn::Free => truncate_text(&self.free_space(), calculated_width),
+ DiskWidgetColumn::Total => truncate_text(&self.total_space(), calculated_width),
+ DiskWidgetColumn::IoRead => truncate_text(&self.io_read, calculated_width),
+ DiskWidgetColumn::IoWrite => truncate_text(&self.io_write, calculated_width),
+ };
+
+ Some(text)
+ }
+
+ fn column_widths<C: DataTableColumn<DiskWidgetColumn>>(
+ data: &[Self], _columns: &[C],
+ ) -> Vec<u16>
+ where
+ Self: Sized,
+ {
+ let mut widths = vec![0; 7];
+
+ data.iter().for_each(|row| {
+ widths[0] = max(widths[0], row.name.len() as u16);
+ widths[1] = max(widths[1], row.mount_point.len() as u16);
+ });
+
+ widths
+ }
+}
+
+pub struct DiskTableWidget {
+ pub table: DataTable<DiskWidgetData, DiskWidgetColumn>,
+}
+
+impl DiskTableWidget {
+ pub fn new(config: &AppConfigFields, colours: &CanvasColours) -> Self {
+ const COLUMNS: [Column<DiskWidgetColumn>; 7] = [
+ Column::soft(DiskWidgetColumn::Disk, Some(0.2)),
+ Column::soft(DiskWidgetColumn::Mount, Some(0.2)),
+ Column::hard(DiskWidgetColumn::Used, 4),
+ Column::hard(DiskWidgetColumn::Free, 6),
+ Column::hard(DiskWidgetColumn::Total, 6),
+ Column::hard(DiskWidgetColumn::IoRead, 7),
+ Column::hard(DiskWidgetColumn::IoWrite, 7),
+ ];
+
+ let props = DataTableProps {
+ title: Some(" Disks ".into()),
+ table_gap: config.table_gap,
+ left_to_right: true,
+ is_basic: config.use_basic_mode,
+ show_table_scroll_position: config.show_table_scroll_position,
+ show_current_entry_when_unfocused: false,
+ };
+
+ let styling = DataTableStyling::from_colours(colours);
+
+ Self {
+ table: DataTable::new(COLUMNS, props, styling),
+ }
+ }
+}