mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-05-03 05:20:32 +00:00
refactor: clean up some table code (#2014)
* clean up column logic * some more cleaning around * clippy
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<_>>()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user