Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Pass render props by reference
Erik Kundt committed 2 years ago
commit fe4d48282e43e725309da0d513620d6afdeb395e
parent 222da206c997008545631dbea6b899eb40e4accb
4 files changed +25 -25
modified src/ui/widget.rs
@@ -67,7 +67,7 @@ pub trait Widget {
    /// Renders a widget to the given frame in the given area.
    ///
    /// Optional props take precedence over the internal ones.
-
    fn render(&self, frame: &mut Frame, area: Rect, props: Option<Box<dyn Any>>);
+
    fn render(&self, frame: &mut Frame, area: Rect, props: Option<&dyn Any>);

    /// Return a mutable reference to this widgets' base view.
    fn base_mut(&mut self) -> &mut BaseView<Self::State, Self::Action>;
@@ -234,10 +234,10 @@ where
        }
    }

-
    fn render(&self, frame: &mut ratatui::Frame, _area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, _area: Rect, props: Option<&dyn Any>) {
        let _props = props
-
            .and_then(WindowProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<WindowProps<Id>>())
+
            .unwrap_or(&self.props);

        let area = frame.size();

@@ -335,12 +335,12 @@ impl<S, A> Widget for Shortcuts<S, A> {
            ShortcutsProps::from_callback(self.base.on_update, state).unwrap_or(self.props.clone());
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        use ratatui::widgets::Table;

        let props = props
-
            .and_then(ShortcutsProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<ShortcutsProps>())
+
            .unwrap_or(&self.props);

        let mut shortcuts = props.shortcuts.iter().peekable();
        let mut row = vec![];
@@ -606,10 +606,10 @@ where
        }
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(TableProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<TableProps<R, W>>())
+
            .unwrap_or(&self.props);

        let widths: Vec<Constraint> = self
            .props
modified src/ui/widget/container.rs
@@ -102,10 +102,10 @@ 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<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(HeaderProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<HeaderProps>())
+
            .unwrap_or(&self.props);

        let widths: Vec<Constraint> = props
            .columns
@@ -275,10 +275,10 @@ 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<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(FooterProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<FooterProps>())
+
            .unwrap_or(&self.props);

        let widths = props
            .columns
@@ -411,10 +411,10 @@ impl<S, A> Widget for Container<S, A> {
        }
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(ContainerProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<ContainerProps>())
+
            .unwrap_or(&self.props);

        let header_h = if self.header.is_some() { 3 } else { 0 };
        let footer_h = if self.footer.is_some() && !props.hide_footer {
modified src/ui/widget/input.rs
@@ -191,10 +191,10 @@ impl<S, A> Widget for TextField<S, A> {
        }
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(TextFieldProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<TextFieldProps>())
+
            .unwrap_or(&self.props);

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

modified src/ui/widget/text.rs
@@ -205,10 +205,10 @@ impl<'a: 'static, S, A> Widget for Paragraph<'a, S, A> {
            ParagraphProps::from_callback(self.base.on_update, state).unwrap_or(self.props.clone());
    }

-
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<Box<dyn Any>>) {
+
    fn render(&self, frame: &mut ratatui::Frame, area: Rect, props: Option<&dyn Any>) {
        let props = props
-
            .and_then(ParagraphProps::from_boxed_any)
-
            .unwrap_or(self.props.clone());
+
            .and_then(|props| props.downcast_ref::<ParagraphProps>())
+
            .unwrap_or(&self.props);

        let [content_area] = Layout::horizontal([Constraint::Min(1)])
            .horizontal_margin(1)