Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Render w/ properties override
Erik Kundt committed 2 years ago
commit 1f1b524ced930a96854358af306265bfec909bb4
parent 047e54b0e38b590b663de58b38d1d7b4d43a08aa
4 files changed +56 -44
modified src/ui/widget.rs
@@ -148,18 +148,21 @@ impl<S, A> View<S, A> for Shortcuts<S, A> {
}

impl<S, A, B: Backend> Widget<S, A, B> for Shortcuts<S, A> {
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
        use ratatui::widgets::Table;

-
        let mut shortcuts = self.props.shortcuts.iter().peekable();
+
        let props = props
+
            .downcast_ref::<ShortcutsProps>()
+
            .unwrap_or(&self.props);
+

+
        let mut shortcuts = props.shortcuts.iter().peekable();
        let mut row = vec![];

        while let Some(shortcut) = shortcuts.next() {
            let short = Text::from(shortcut.0.clone()).style(style::gray());
            let long = Text::from(shortcut.1.clone()).style(style::gray().dim());
            let spacer = Text::from(String::new());
-
            let divider =
-
                Text::from(format!(" {} ", self.props.divider)).style(style::gray().dim());
+
            let divider = Text::from(format!(" {} ", props.divider)).style(style::gray().dim());

            row.push((shortcut.0.chars().count(), short));
            row.push((1, spacer));
@@ -454,7 +457,11 @@ where
    B: Backend,
    R: ToRow + Clone + Debug + 'static,
{
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
+
        let props = props
+
            .downcast_ref::<TableProps<'_, R>>()
+
            .unwrap_or(&self.props);
+

        let header_height = if self.header.is_some() { 3 } else { 0 };
        let [header_area, table_area] =
            Layout::vertical([Constraint::Length(header_height), Constraint::Min(1)]).areas(area);
@@ -465,30 +472,26 @@ where
            .filter_map(|c| if !c.skip { Some(c.width) } else { None })
            .collect();

-
        let widths = if area.width < self.props.cutoff as u16 {
-
            widths
-
                .iter()
-
                .take(self.props.cutoff_after)
-
                .collect::<Vec<_>>()
+
        let widths = if area.width < props.cutoff as u16 {
+
            widths.iter().take(props.cutoff_after).collect::<Vec<_>>()
        } else {
            widths.iter().collect::<Vec<_>>()
        };

-
        let borders = match (self.header.is_some(), self.props.has_footer) {
+
        let borders = match (self.header.is_some(), props.has_footer) {
            (false, false) => Borders::ALL,
            (true, false) => Borders::BOTTOM | Borders::LEFT | Borders::RIGHT,
            (false, true) => Borders::TOP | Borders::LEFT | Borders::RIGHT,
            (true, true) => Borders::LEFT | Borders::RIGHT,
        };

-
        if !self.props.items.is_empty() {
-
            let rows = self
-
                .props
+
        if !props.items.is_empty() {
+
            let rows = props
                .items
                .iter()
                .map(|item| {
                    let mut cells = vec![];
-
                    let mut it = self.props.columns.iter();
+
                    let mut it = props.columns.iter();

                    for cell in item.to_row() {
                        if let Some(col) = it.next() {
@@ -509,7 +512,7 @@ where
                .column_spacing(1)
                .block(
                    Block::default()
-
                        .border_style(style::border(self.props.focus))
+
                        .border_style(style::border(props.focus))
                        .border_type(BorderType::Rounded)
                        .borders(borders),
                )
@@ -522,7 +525,7 @@ where
            frame.render_stateful_widget(rows, table_area, &mut self.state.clone());
        } else {
            let block = Block::default()
-
                .border_style(style::border(self.props.focus))
+
                .border_style(style::border(props.focus))
                .border_type(BorderType::Rounded)
                .borders(borders);

modified src/ui/widget/container.rs
@@ -115,9 +115,12 @@ impl<'a: 'static, S, A> View<S, A> for Header<'a, S, A> {
}

impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Header<'a, S, A> {
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
-
        let widths: Vec<Constraint> = self
-
            .props
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
+
        let props = props
+
            .downcast_ref::<HeaderProps<'_>>()
+
            .unwrap_or(&self.props);
+

+
        let widths: Vec<Constraint> = props
            .columns
            .iter()
            .filter_map(|column| {
@@ -128,8 +131,7 @@ impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Header<'a, S, A> {
                }
            })
            .collect();
-
        let cells = self
-
            .props
+
        let cells = props
            .columns
            .iter()
            .filter_map(|column| {
@@ -141,11 +143,8 @@ impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Header<'a, S, A> {
            })
            .collect::<Vec<_>>();

-
        let widths = if area.width < self.props.cutoff as u16 {
-
            widths
-
                .iter()
-
                .take(self.props.cutoff_after)
-
                .collect::<Vec<_>>()
+
        let widths = if area.width < props.cutoff as u16 {
+
            widths.iter().take(props.cutoff_after).collect::<Vec<_>>()
        } else {
            widths.iter().collect::<Vec<_>>()
        };
@@ -153,7 +152,7 @@ impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Header<'a, S, A> {
        // Render header
        let block = HeaderBlock::default()
            .borders(Borders::ALL)
-
            .border_style(style::border(self.props.focus))
+
            .border_style(style::border(props.focus))
            .border_type(BorderType::Rounded);

        let header_layout = Layout::default()
@@ -300,9 +299,12 @@ impl<'a, S, A> Footer<'a, S, A> {
}

impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Footer<'a, S, A> {
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
-
        let widths = self
-
            .props
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
+
        let props = props
+
            .downcast_ref::<FooterProps<'_>>()
+
            .unwrap_or(&self.props);
+

+
        let widths = props
            .columns
            .iter()
            .map(|c| match c.width {
@@ -312,8 +314,7 @@ impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Footer<'a, S, A> {
            .collect::<Vec<_>>();

        let layout = Layout::horizontal(widths).split(area);
-
        let cells = self
-
            .props
+
        let cells = props
            .columns
            .iter()
            .map(|c| c.text.clone())
@@ -330,7 +331,7 @@ impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> 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(), props.focus);
        }
    }
}
modified src/ui/widget/input.rs
@@ -184,15 +184,19 @@ impl<S, A> View<S, A> for TextField<S, A> {
}

impl<S, A, B: Backend> Widget<S, A, B> for TextField<S, A> {
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
+
        let props = props
+
            .downcast_ref::<TextFieldProps>()
+
            .unwrap_or(&self.props);
+

        let layout = Layout::vertical(Constraint::from_lengths([1, 1])).split(area);

-
        let input = self.props.text.as_str();
-
        let label = format!(" {} ", self.props.title);
+
        let input = props.text.as_str();
+
        let label = format!(" {} ", props.title);
        let overline = String::from("▔").repeat(area.width as usize);
-
        let cursor_pos = self.props.cursor_position as u16;
+
        let cursor_pos = props.cursor_position as u16;

-
        if self.props.inline_label {
+
        if props.inline_label {
            let top_layout = Layout::horizontal([
                Constraint::Length(label.chars().count() as u16),
                Constraint::Length(1),
@@ -209,7 +213,7 @@ impl<S, A, B: Backend> Widget<S, A, B> for TextField<S, A> {
            frame.render_widget(input, top_layout[2]);
            frame.render_widget(overline, layout[1]);

-
            if self.props.show_cursor {
+
            if props.show_cursor {
                frame.set_cursor(top_layout[2].x + cursor_pos, top_layout[2].y)
            }
        } else {
@@ -225,7 +229,7 @@ impl<S, A, B: Backend> Widget<S, A, B> for TextField<S, A> {
            frame.render_widget(top, layout[0]);
            frame.render_widget(bottom, layout[1]);

-
            if self.props.show_cursor {
+
            if props.show_cursor {
                frame.set_cursor(area.x + cursor_pos, area.y)
            }
        }
modified src/ui/widget/text.rs
@@ -206,17 +206,21 @@ impl<'a: 'static, S, A> View<S, A> for Paragraph<'a, S, A> {
}

impl<'a: 'static, S, A, B: Backend> Widget<S, A, B> for Paragraph<'a, S, A> {
-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, _props: &dyn Any) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: &dyn Any) {
+
        let props = props
+
            .downcast_ref::<ParagraphProps<'_>>()
+
            .unwrap_or(&self.props);
+

        let block = Block::default()
            .borders(Borders::LEFT | Borders::RIGHT)
            .border_type(BorderType::Rounded)
-
            .border_style(style::border(self.props.focus));
+
            .border_style(style::border(props.focus));
        frame.render_widget(block, area);

        let [content_area] = Layout::horizontal([Constraint::Min(1)])
            .horizontal_margin(2)
            .areas(area);
-
        let content = ratatui::widgets::Paragraph::new(self.props.content.clone())
+
        let content = ratatui::widgets::Paragraph::new(props.content.clone())
            .scroll((self.offset as u16, 0));

        frame.render_widget(content, content_area);