lib: Rework render width-dependent table column display

This commit is contained in:
Erik Kundt
2024-06-13 12:37:31 +02:00
parent 4805b1aed4
commit 68a4a82165
3 changed files with 87 additions and 28 deletions
+5
View File
@@ -22,6 +22,11 @@ use super::terminal;
const RENDERING_TICK_RATE: Duration = Duration::from_millis(250);
const INLINE_HEIGHT: usize = 20;
pub const RENDER_WIDTH_XSMALL: usize = 50;
pub const RENDER_WIDTH_SMALL: usize = 70;
pub const RENDER_WIDTH_MEDIUM: usize = 150;
pub const RENDER_WIDTH_LARGE: usize = usize::MAX;
/// The `Frontend` runs an applications' view concurrently. It handles
/// terminal events as well as state updates and renders the view accordingly.
///
+74 -10
View File
@@ -8,14 +8,58 @@ use ratatui::widgets::{Block, BorderType, Borders, Row};
use crate::ui::ext::{FooterBlock, FooterBlockType, HeaderBlock};
use crate::ui::theme::style;
use crate::ui::{RENDER_WIDTH_LARGE, RENDER_WIDTH_MEDIUM, RENDER_WIDTH_SMALL};
use super::{PredefinedLayout, RenderProps, View, ViewProps, Widget};
#[derive(Clone, Debug)]
pub struct ColumnView {
small: bool,
medium: bool,
large: bool,
}
impl ColumnView {
pub fn all() -> Self {
Self {
small: true,
medium: true,
large: true,
}
}
pub fn small(mut self) -> Self {
self.small = true;
self
}
pub fn medium(mut self) -> Self {
self.medium = true;
self
}
pub fn large(mut self) -> Self {
self.large = true;
self
}
}
impl Default for ColumnView {
fn default() -> Self {
Self {
small: false,
medium: false,
large: false,
}
}
}
#[derive(Clone, Debug)]
pub struct Column<'a> {
pub text: Text<'a>,
pub width: Constraint,
pub skip: bool,
pub view: ColumnView,
}
impl<'a> Column<'a> {
@@ -24,6 +68,7 @@ impl<'a> Column<'a> {
text: text.into(),
width,
skip: false,
view: ColumnView::all(),
}
}
@@ -31,6 +76,28 @@ impl<'a> Column<'a> {
self.skip = skip;
self
}
pub fn hide_small(mut self) -> Self {
self.view = ColumnView::default().medium().large();
self
}
pub fn hide_medium(mut self) -> Self {
self.view = ColumnView::default().large();
self
}
pub fn displayed(&self, area_width: usize) -> bool {
if area_width < RENDER_WIDTH_SMALL {
self.view.small
} else if area_width < RENDER_WIDTH_MEDIUM {
self.view.medium
} else if area_width < RENDER_WIDTH_LARGE {
self.view.large
} else {
true
}
}
}
#[derive(Clone, Debug)]
@@ -86,22 +153,25 @@ impl<'a: 'static, S, M> View for Header<S, M> {
.and_then(|props| props.inner_ref::<HeaderProps>())
.unwrap_or(&default);
let width = render.area.width.saturating_sub(2);
let widths: Vec<Constraint> = props
.columns
.iter()
.filter_map(|column| {
if !column.skip {
Some(column.width)
.filter_map(|c| {
if !c.skip && c.displayed(width as usize) {
Some(c.width)
} else {
None
}
})
.collect();
let cells = props
.columns
.iter()
.filter_map(|column| {
if !column.skip {
if !column.skip && column.displayed(width as usize) {
Some(column.text.clone())
} else {
None
@@ -109,12 +179,6 @@ impl<'a: 'static, S, M> View for Header<S, M> {
})
.collect::<Vec<_>>();
let widths = if render.area.width < props.cutoff as u16 {
widths.iter().take(props.cutoff_after).collect::<Vec<_>>()
} else {
widths.iter().collect::<Vec<_>>()
};
// Render header
let block = HeaderBlock::default()
.borders(Borders::ALL)
+8 -18
View File
@@ -30,8 +30,6 @@ where
pub selected: Option<usize>,
pub columns: Vec<Column<'a>>,
pub has_footer: bool,
pub cutoff: usize,
pub cutoff_after: usize,
pub page_size: usize,
}
@@ -44,8 +42,6 @@ where
items: vec![],
columns: vec![],
has_footer: false,
cutoff: usize::MAX,
cutoff_after: usize::MAX,
page_size: 1,
selected: Some(0),
}
@@ -76,12 +72,6 @@ where
self
}
pub fn cutoff(mut self, cutoff: usize, cutoff_after: usize) -> Self {
self.cutoff = cutoff;
self.cutoff_after = cutoff_after;
self
}
pub fn page_size(mut self, page_size: usize) -> Self {
self.page_size = page_size;
self
@@ -225,15 +215,15 @@ where
let widths: Vec<Constraint> = props
.columns
.iter()
.filter_map(|c| if !c.skip { Some(c.width) } else { None })
.filter_map(|c| {
if !c.skip && c.displayed(render.area.width as usize) {
Some(c.width)
} else {
None
}
})
.collect();
let widths = if render.area.width < props.cutoff as u16 {
widths.iter().take(props.cutoff_after).collect::<Vec<_>>()
} else {
widths.iter().collect::<Vec<_>>()
};
if !props.items.is_empty() {
let rows = props
.items
@@ -244,7 +234,7 @@ where
for cell in item.to_row() {
if let Some(col) = it.next() {
if !col.skip {
if !col.skip && col.displayed(render.area.width as usize) {
cells.push(cell.clone());
}
} else {