Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Render widgets with focus
Erik Kundt committed 2 years ago
commit 4cb8585fc355ed351b0d6afda3b34b33e3d1d568
parent 5365ceee8b602e6badef677d94b8362b212e9dc6
4 files changed +17 -50
modified src/ui/theme.rs
@@ -43,7 +43,7 @@ pub mod style {

    pub fn border(focus: bool) -> Style {
        if focus {
-
            Style::default().fg(Color::Indexed(239))
+
            Style::default().fg(Color::Indexed(238))
        } else {
            Style::default().fg(Color::Indexed(236))
        }
modified src/ui/widget.rs
@@ -276,7 +276,7 @@ where
            .and_then(|id| self.pages.get(id));

        if let Some(page) = page {
-
            page.render(frame, area, None);
+
            page.render(frame, area, Some(RenderProps { focus: true }));
        }
    }

@@ -435,7 +435,6 @@ where
{
    pub items: Vec<R>,
    pub selected: Option<usize>,
-
    pub focus: bool,
    pub columns: Vec<Column<'a>>,
    pub has_footer: bool,
    pub cutoff: usize,
@@ -450,7 +449,6 @@ where
    fn default() -> Self {
        Self {
            items: vec![],
-
            focus: false,
            columns: vec![],
            has_footer: false,
            cutoff: usize::MAX,
modified src/ui/widget/container.rs
@@ -17,7 +17,6 @@ pub struct HeaderProps<'a> {
    pub columns: Vec<Column<'a>>,
    pub cutoff: usize,
    pub cutoff_after: usize,
-
    pub focus: bool,
}

impl<'a> HeaderProps<'a> {
@@ -26,11 +25,6 @@ impl<'a> HeaderProps<'a> {
        self
    }

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.focus = focus;
-
        self
-
    }
-

    pub fn cutoff(mut self, cutoff: usize, cutoff_after: usize) -> Self {
        self.cutoff = cutoff;
        self.cutoff_after = cutoff_after;
@@ -44,7 +38,6 @@ impl<'a> Default for HeaderProps<'a> {
            columns: vec![],
            cutoff: usize::MAX,
            cutoff_after: usize::MAX,
-
            focus: false,
        }
    }
}
@@ -64,11 +57,6 @@ impl<'a, S, A> Header<'a, S, A> {
        self
    }

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.props.focus = focus;
-
        self
-
    }
-

    pub fn cutoff(mut self, cutoff: usize, cutoff_after: usize) -> Self {
        self.props.cutoff = cutoff;
        self.props.cutoff_after = cutoff_after;
@@ -101,7 +89,7 @@ impl<'a: 'static, S, A> Widget for Header<'a, S, A> {
            .unwrap_or(self.props.clone());
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: Option<RenderProps>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<RenderProps>) {
        let widths: Vec<Constraint> = self
            .props
            .columns
@@ -136,10 +124,12 @@ impl<'a: 'static, S, A> Widget for Header<'a, S, A> {
            widths.iter().collect::<Vec<_>>()
        };

+
        let focus = props.map(|props| props.focus).unwrap_or(false);
+

        // Render header
        let block = HeaderBlock::default()
            .borders(Borders::ALL)
-
            .border_style(style::border(self.props.focus))
+
            .border_style(style::border(focus))
            .border_type(BorderType::Rounded);

        let header_layout = Layout::default()
@@ -169,7 +159,6 @@ pub struct FooterProps<'a> {
    pub columns: Vec<Column<'a>>,
    pub cutoff: usize,
    pub cutoff_after: usize,
-
    pub focus: bool,
}

impl<'a> FooterProps<'a> {
@@ -183,11 +172,6 @@ impl<'a> FooterProps<'a> {
        self.cutoff_after = cutoff_after;
        self
    }
-

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.focus = focus;
-
        self
-
    }
}

impl<'a> Default for FooterProps<'a> {
@@ -196,7 +180,6 @@ impl<'a> Default for FooterProps<'a> {
            columns: vec![],
            cutoff: usize::MAX,
            cutoff_after: usize::MAX,
-
            focus: false,
        }
    }
}
@@ -222,11 +205,6 @@ impl<'a, S, A> Footer<'a, S, A> {
        self
    }

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.props.focus = focus;
-
        self
-
    }
-

    fn render_cell(
        &self,
        frame: &mut ratatui::Frame,
@@ -275,7 +253,7 @@ impl<'a: 'static, S, A> Widget for Footer<'a, S, A> {
            .unwrap_or(self.props.clone());
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: Option<RenderProps>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<RenderProps>) {
        let widths = self
            .props
            .columns
@@ -298,6 +276,8 @@ impl<'a: 'static, S, A> Widget for Footer<'a, S, A> {
        let last = cells.len().saturating_sub(1);
        let len = cells.len();

+
        let focus = props.as_ref().map(|props| props.focus).unwrap_or_default();
+

        for (i, (cell, area)) in cells.into_iter().enumerate() {
            let block_type = match i {
                0 if len == 1 => FooterBlockType::Single,
@@ -305,7 +285,7 @@ impl<'a: 'static, S, A> Widget for Footer<'a, S, A> {
                _ if i == last => FooterBlockType::End,
                _ => FooterBlockType::Repeat,
            };
-
            self.render_cell(frame, *area, block_type, cell.clone(), self.props.focus);
+
            self.render_cell(frame, *area, block_type, cell.clone(), focus);
        }
    }

@@ -316,7 +296,6 @@ impl<'a: 'static, S, A> Widget for Footer<'a, S, A> {

#[derive(Clone, Default)]
pub struct ContainerProps {
-
    focus: bool,
    hide_footer: bool,
}

@@ -325,11 +304,6 @@ impl ContainerProps {
        self.hide_footer = hide;
        self
    }
-

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.focus = focus;
-
        self
-
    }
}

impl Properties for ContainerProps {}
@@ -409,7 +383,7 @@ impl<S, A> Widget for Container<S, A> {
        }
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: Option<RenderProps>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<RenderProps>) {
        let header_h = if self.header.is_some() { 3 } else { 0 };
        let footer_h = if self.footer.is_some() && !self.props.hide_footer {
            3
@@ -434,22 +408,24 @@ impl<S, A> Widget for Container<S, A> {
            (true, true) => Borders::LEFT | Borders::RIGHT,
        };

+
        let focus = props.as_ref().map(|props| props.focus).unwrap_or_default();
+

        let block = Block::default()
-
            .border_style(style::border(self.props.focus))
+
            .border_style(style::border(focus))
            .border_type(BorderType::Rounded)
            .borders(borders);
        frame.render_widget(block.clone(), content_area);

        if let Some(header) = &self.header {
-
            header.render(frame, header_area, None);
+
            header.render(frame, header_area, props.clone());
        }

        if let Some(content) = &self.content {
-
            content.render(frame, block.inner(content_area), None);
+
            content.render(frame, block.inner(content_area), props.clone());
        }

        if let Some(footer) = &self.footer {
-
            footer.render(frame, footer_area, None);
+
            footer.render(frame, footer_area, props);
        }
    }

modified src/ui/widget/text.rs
@@ -10,7 +10,6 @@ use super::{BaseView, Properties, RenderProps, Widget, WidgetState};
#[derive(Clone)]
pub struct ParagraphProps<'a> {
    pub content: Text<'a>,
-
    pub focus: bool,
    pub has_header: bool,
    pub has_footer: bool,
    pub page_size: usize,
@@ -27,18 +26,12 @@ impl<'a> ParagraphProps<'a> {
        self.content = text.clone();
        self
    }
-

-
    pub fn focus(mut self, focus: bool) -> Self {
-
        self.focus = focus;
-
        self
-
    }
}

impl<'a> Default for ParagraphProps<'a> {
    fn default() -> Self {
        Self {
            content: Text::raw(""),
-
            focus: false,
            has_header: false,
            has_footer: false,
            page_size: 1,