Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
lib: Unify table and text scrolling
Merged did:key:z6MkgFq6...nBGz opened 1 year ago
7 files changed +71 -49 25752aaf 4803308e
modified bin/commands/inbox/select/ui.rs
@@ -18,7 +18,8 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps,
};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::list::{Table, TableProps, TableUtils};
+
use tui::ui::widget::list::{Table, TableProps};
+
use tui::ui::widget::utils;
use tui::ui::widget::{self, ViewProps};
use tui::ui::widget::{RenderProps, ToWidget, View};

@@ -290,7 +291,13 @@ fn browse_footer<'a>(props: &BrowserProps<'a>) -> Vec<Column<'a>> {

    let progress = props
        .selected
-
        .map(|selected| TableUtils::progress(selected, props.notifications.len(), props.page_size))
+
        .map(|selected| {
+
            utils::scroll::percent_absolute(
+
                selected.saturating_sub(props.page_size),
+
                props.notifications.len(),
+
                props.page_size,
+
            )
+
        })
        .unwrap_or_default();
    let progress = span::default(&format!("{}%", progress)).dim();

modified bin/commands/issue/select/ui.rs
@@ -21,7 +21,8 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps,
};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::list::{Table, TableProps, TableUtils};
+
use tui::ui::widget::list::{Table, TableProps};
+
use tui::ui::widget::utils;
use tui::ui::widget::ViewProps;
use tui::ui::widget::{RenderProps, ToWidget, View};

@@ -315,7 +316,13 @@ fn browse_footer<'a>(props: &BrowserProps<'a>, selected: Option<usize>) -> Vec<C
    ]);

    let progress = selected
-
        .map(|selected| TableUtils::progress(selected, props.issues.len(), props.page_size))
+
        .map(|selected| {
+
            utils::scroll::percent_absolute(
+
                selected.saturating_sub(props.page_size),
+
                props.issues.len(),
+
                props.page_size,
+
            )
+
        })
        .unwrap_or_default();
    let progress = span::default(&format!("{}%", progress)).dim();

modified bin/commands/patch/select/ui.rs
@@ -23,7 +23,8 @@ use tui::ui::widget::container::{
    Column, Container, ContainerProps, Footer, FooterProps, Header, HeaderProps,
};
use tui::ui::widget::input::{TextField, TextFieldProps};
-
use tui::ui::widget::list::{Table, TableProps, TableUtils};
+
use tui::ui::widget::list::{Table, TableProps};
+
use tui::ui::widget::utils;
use tui::ui::widget::ViewProps;
use tui::ui::widget::{RenderProps, ToWidget, View};

@@ -339,7 +340,13 @@ fn browser_footer<'a>(props: &BrowserProps<'a>, selected: Option<usize>) -> Vec<
    ]);

    let progress = selected
-
        .map(|selected| TableUtils::progress(selected, props.patches.len(), props.page_size))
+
        .map(|selected| {
+
            utils::scroll::percent_absolute(
+
                selected.saturating_sub(props.page_size),
+
                props.patches.len(),
+
                props.page_size,
+
            )
+
        })
        .unwrap_or_default();
    let progress = span::default(&format!("{}%", progress)).dim();

modified src/ui/widget.rs
@@ -2,6 +2,7 @@ pub mod container;
pub mod input;
pub mod list;
pub mod text;
+
pub mod utils;
pub mod window;

use std::any::Any;
modified src/ui/widget/list.rs
@@ -273,26 +273,3 @@ where
        self.state.selected().map(ViewState::USize)
    }
}
-

-
pub struct TableUtils {}
-

-
impl TableUtils {
-
    pub fn progress(selected: usize, len: usize, page_size: usize) -> usize {
-
        let step = selected;
-
        let page_size = page_size as f64;
-
        let len = len as f64;
-

-
        let lines = page_size + step.saturating_sub(page_size as usize) as f64;
-
        let progress = (lines / len * 100.0).ceil();
-

-
        if progress > 97.0 {
-
            Self::map_range((0.0, progress), (0.0, 100.0), progress) as usize
-
        } else {
-
            progress as usize
-
        }
-
    }
-

-
    fn map_range(from: (f64, f64), to: (f64, f64), value: f64) -> f64 {
-
        to.0 + (value - from.0) * (to.1 - to.0) / (from.1 - from.0)
-
    }
-
}
modified src/ui/widget/text.rs
@@ -1,10 +1,12 @@
use std::marker::PhantomData;

+
use termion::event::Key;
+

use ratatui::layout::{Constraint, Layout};
use ratatui::text::Text;
use ratatui::Frame;
-
use termion::event::Key;

+
use super::utils;
use super::{RenderProps, View, ViewProps, ViewState};

#[derive(Clone)]
@@ -81,14 +83,15 @@ impl<S, M> TextArea<S, M> {

    fn prev(&mut self, len: usize, page_size: usize) -> (u16, u16) {
        self.state.offset = self.state.offset.saturating_sub(1);
-
        self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
        self.state.progress = utils::scroll::percent_absolute(self.state.offset, len, page_size);
        self.scroll()
    }

    fn next(&mut self, len: usize, page_size: usize) -> (u16, u16) {
        if self.state.progress < 100 {
            self.state.offset = self.state.offset.saturating_add(1);
-
            self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
            self.state.progress =
+
                utils::scroll::percent_absolute(self.state.offset, len, page_size);
        }

        self.scroll()
@@ -96,7 +99,7 @@ impl<S, M> TextArea<S, M> {

    fn prev_page(&mut self, len: usize, page_size: usize) -> (u16, u16) {
        self.state.offset = self.state.offset.saturating_sub(page_size);
-
        self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
        self.state.progress = utils::scroll::percent_absolute(self.state.offset, len, page_size);
        self.scroll()
    }

@@ -104,34 +107,21 @@ impl<S, M> TextArea<S, M> {
        let end = len.saturating_sub(page_size);

        self.state.offset = std::cmp::min(self.state.offset.saturating_add(page_size), end);
-
        self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
        self.state.progress = utils::scroll::percent_absolute(self.state.offset, len, page_size);
        self.scroll()
    }

    fn begin(&mut self, len: usize, page_size: usize) -> (u16, u16) {
        self.state.offset = 0;
-
        self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
        self.state.progress = utils::scroll::percent_absolute(self.state.offset, len, page_size);
        self.scroll()
    }

    fn end(&mut self, len: usize, page_size: usize) -> (u16, u16) {
        self.state.offset = len.saturating_sub(page_size);
-
        self.state.progress = Self::scroll_percent(self.state.offset, len, page_size);
+
        self.state.progress = utils::scroll::percent_absolute(self.state.offset, len, page_size);
        self.scroll()
    }
-

-
    fn scroll_percent(offset: usize, len: usize, height: usize) -> usize {
-
        if height >= len {
-
            100
-
        } else {
-
            let y = offset as f64;
-
            let h = height as f64;
-
            let t = len.saturating_sub(1) as f64;
-
            let v = y / (t - h) * 100_f64;
-

-
            std::cmp::max(0, std::cmp::min(100, v as usize))
-
        }
-
    }
}

impl<S, M> View for TextArea<S, M>
added src/ui/widget/utils.rs
@@ -0,0 +1,33 @@
+
pub mod scroll {
+
    pub fn percent_seen(selected: usize, len: usize, page_size: usize) -> usize {
+
        let step = selected;
+
        let page_size = page_size as f64;
+
        let len = len as f64;
+

+
        let lines = page_size + step.saturating_sub(page_size as usize) as f64;
+
        let progress = (lines / len * 100.0).ceil();
+

+
        if progress > 97.0 {
+
            map_range((0.0, progress), (0.0, 100.0), progress) as usize
+
        } else {
+
            progress as usize
+
        }
+
    }
+

+
    pub fn percent_absolute(offset: usize, len: usize, height: usize) -> usize {
+
        if height >= len {
+
            100
+
        } else {
+
            let y = offset as f64;
+
            let h = height as f64;
+
            let t = len.saturating_sub(1) as f64;
+
            let v = y / (t - h) * 100_f64;
+

+
            std::cmp::max(0, std::cmp::min(100, v as usize))
+
        }
+
    }
+

+
    fn map_range(from: (f64, f64), to: (f64, f64), value: f64) -> f64 {
+
        to.0 + (value - from.0) * (to.1 - to.0) / (from.1 - from.0)
+
    }
+
}