refactor: clean up some table code (#2014)

* clean up column logic

* some more cleaning around

* clippy
This commit is contained in:
Clement Tsang
2026-04-11 02:28:38 -04:00
committed by GitHub
parent edd20d5ade
commit 6970f0ef61
4 changed files with 57 additions and 84 deletions
+28 -41
View File
@@ -62,6 +62,8 @@ pub trait DataTableColumn<H: ColumnHeader> {
fn is_hidden(&self) -> bool;
fn set_hidden(&mut self, hidden: bool);
/// The actually displayed "header".
fn header(&self) -> Cow<'static, str>;
@@ -112,12 +114,25 @@ impl<H: ColumnHeader> DataTableColumn<H> for Column<H> {
self.is_hidden
}
#[inline]
fn set_hidden(&mut self, hidden: bool) {
self.is_hidden = hidden;
}
fn header(&self) -> Cow<'static, str> {
self.inner.text()
}
}
impl<H: ColumnHeader> Column<H> {
pub const fn new(inner: H) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::FollowHeader,
is_hidden: false,
}
}
pub const fn hard(inner: H, width: u16) -> Self {
Self {
inner,
@@ -177,7 +192,7 @@ where
continue;
}
match &column.bounds() {
let new_width = match &column.bounds() {
ColumnWidthBounds::Soft {
desired,
max_percentage,
@@ -195,50 +210,22 @@ where
},
min_width,
);
let space_taken = min(min(soft_limit, *desired), total_width_left);
if stop_allocating_space(space_taken, total_width_left) {
break;
} else {
total_width_left =
total_width_left.saturating_sub(space_taken + COLUMN_SPACING);
// SAFETY: This is safe as we call `stop_allocating_space` which checks that
// the value pushed is greater than zero.
unsafe {
calculated_widths.push(NonZeroU16::new_unchecked(space_taken));
}
}
min(min(soft_limit, *desired), total_width_left)
}
ColumnWidthBounds::Hard(width) => {
let min_width = *width;
if stop_allocating_space(min_width, total_width_left) {
break;
} else {
total_width_left =
total_width_left.saturating_sub(min_width + COLUMN_SPACING);
ColumnWidthBounds::Hard(width) => *width,
ColumnWidthBounds::FollowHeader => column.header_len() as u16,
};
// SAFETY: This is safe as we call `stop_allocating_space` which checks that
// the value pushed is greater than zero.
unsafe {
calculated_widths.push(NonZeroU16::new_unchecked(min_width));
}
}
}
ColumnWidthBounds::FollowHeader => {
let min_width = column.header_len() as u16;
if stop_allocating_space(min_width, total_width_left) {
break;
} else {
total_width_left =
total_width_left.saturating_sub(min_width + COLUMN_SPACING);
if stop_allocating_space(new_width, total_width_left) {
break;
} else {
total_width_left = total_width_left.saturating_sub(new_width + COLUMN_SPACING);
// SAFETY: This is safe as we call `stop_allocating_space` which checks that
// the value pushed is greater than zero.
unsafe {
calculated_widths.push(NonZeroU16::new_unchecked(min_width));
}
}
// SAFETY: This is safe as we call `stop_allocating_space` which checks that
// the value pushed is greater than zero.
unsafe {
calculated_widths.push(NonZeroU16::new_unchecked(new_width));
}
}
}
+1 -2
View File
@@ -50,8 +50,7 @@ pub struct DrawInfo {
impl DrawInfo {
pub fn is_on_widget(&self) -> bool {
matches!(self.selection_state, SelectionState::Selected)
|| matches!(self.selection_state, SelectionState::Expanded)
!matches!(self.selection_state, SelectionState::NotSelected)
}
pub fn is_expanded(&self) -> bool {
+25 -38
View File
@@ -8,7 +8,7 @@ use super::{
ColumnHeader, ColumnWidthBounds, DataTable, DataTableColumn, DataTableProps, DataTableState,
DataTableStyling, DataToCell,
};
use crate::utils::strings::truncate_to_text;
use crate::{canvas::components::data_table::Column, utils::strings::truncate_to_text};
/// Denotes the sort order.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -123,53 +123,52 @@ pub trait SortsRow {
fn sort_data(&self, data: &mut [Self::DataType], descending: bool);
}
/// A wrapper around [`Column`] that also has sorting capabilities.
#[derive(Debug, Clone)]
pub struct SortColumn<T> {
pub struct SortColumn<H> {
/// The inner column header.
inner: T,
column: Column<H>,
/// The default sort order.
pub default_order: SortOrder,
/// A restriction on this column's width.
pub bounds: ColumnWidthBounds,
/// Marks that this column is currently "hidden", and should *always* be
/// skipped.
pub is_hidden: bool,
}
impl<D, T> DataTableColumn<T> for SortColumn<T>
impl<D, H> DataTableColumn<H> for SortColumn<H>
where
T: ColumnHeader + SortsRow<DataType = D>,
H: ColumnHeader + SortsRow<DataType = D>,
{
#[inline]
fn inner(&self) -> &T {
&self.inner
fn inner(&self) -> &H {
self.column.inner()
}
#[inline]
fn inner_mut(&mut self) -> &mut T {
&mut self.inner
fn inner_mut(&mut self) -> &mut H {
self.column.inner_mut()
}
#[inline]
fn bounds(&self) -> ColumnWidthBounds {
self.bounds
self.column.bounds()
}
#[inline]
fn bounds_mut(&mut self) -> &mut ColumnWidthBounds {
&mut self.bounds
self.column.bounds_mut()
}
#[inline]
fn is_hidden(&self) -> bool {
self.is_hidden
self.column.is_hidden()
}
#[inline]
fn set_hidden(&mut self, hidden: bool) {
self.column.set_hidden(hidden);
}
fn header(&self) -> Cow<'static, str> {
self.inner.header()
self.column.header()
}
fn header_len(&self) -> usize {
@@ -186,10 +185,8 @@ where
/// ([`SortOrder::Ascending`]).
pub fn new(inner: T) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::FollowHeader,
is_hidden: false,
default_order: SortOrder::default(),
column: Column::new(inner),
default_order: SortOrder::const_default(),
}
}
@@ -197,9 +194,7 @@ where
/// and sorts by default in ascending order ([`SortOrder::Ascending`]).
pub const fn hard(inner: T, width: u16) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::Hard(width),
is_hidden: false,
column: Column::hard(inner, width),
default_order: SortOrder::const_default(),
}
}
@@ -208,12 +203,7 @@ where
/// and sorts by default in ascending order ([`SortOrder::Ascending`]).
pub const fn soft(inner: T, max_percentage: Option<f32>) -> Self {
Self {
inner,
bounds: ColumnWidthBounds::Soft {
desired: 0,
max_percentage,
},
is_hidden: false,
column: Column::soft(inner, max_percentage),
default_order: SortOrder::const_default(),
}
}
@@ -228,7 +218,7 @@ where
/// associated data.
pub fn sort_by(&self, data: &mut [D], order: SortOrder) {
let descending = matches!(order, SortOrder::Descending);
self.inner.sort_data(data, descending);
self.column.inner().sort_data(data, descending);
}
}
@@ -277,10 +267,7 @@ where
/// Toggles the current sort order.
pub fn toggle_order(&mut self) {
self.sort_type.order = match self.sort_type.order {
SortOrder::Ascending => SortOrder::Descending,
SortOrder::Descending => SortOrder::Ascending,
}
self.sort_type.order = self.sort_type.order.rev();
}
/// Given some `x` and `y`, if possible, select the corresponding column or
+3 -3
View File
@@ -925,7 +925,7 @@ impl ProcWidgetState {
fn hide_column(&mut self, column: ProcWidgetColumn) {
if let Some(index) = self.column_mapping.get_index_of(&column) {
if let Some(col) = self.table.columns.get_mut(index) {
col.is_hidden = true;
col.set_hidden(true);
if self.table.sort_index() == index {
self.table.set_sort_index(self.default_sort_index);
@@ -939,7 +939,7 @@ impl ProcWidgetState {
fn show_column(&mut self, column: ProcWidgetColumn) {
if let Some(index) = self.column_mapping.get_index_of(&column) {
if let Some(col) = self.table.columns.get_mut(index) {
col.is_hidden = false;
col.set_hidden(false);
}
}
}
@@ -1061,7 +1061,7 @@ impl ProcWidgetState {
self.table
.columns
.iter()
.filter(|c| !c.is_hidden)
.filter(|c| !c.is_hidden())
.map(|c| c.inner().text())
.collect::<Vec<_>>()
}