Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Rework render width-dependent table column display
Erik Kundt committed 1 year ago
commit 68a4a82165d765e72e48048e1e34fb888fe9ec81
parent 4805b1aed40699a633f535eab6ec4d5bfbf598fb
3 files changed +87 -28
modified src/ui.rs
@@ -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.
///
modified src/ui/widget/container.rs
@@ -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)
modified src/ui/widget/list.rs
@@ -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 {