Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Improve widget state conversions
Erik Kundt committed 2 years ago
commit f327d8670e04e2a7819904422876ab80ebb86764
parent e76c69b5d0be5a4c92b91f096768f5a714f4d933
4 files changed +41 -16
modified src/ui/widget.rs
@@ -21,7 +21,7 @@ use super::{layout, span};
pub type BoxedWidget<S, A> = Box<dyn Widget<State = S, Action = A>>;

pub type UpdateCallback<S> = fn(&S) -> Box<dyn Any>;
-
pub type EventCallback<A> = fn(&dyn Any, UnboundedSender<A>);
+
pub type EventCallback<A> = fn(Box<dyn Any>, UnboundedSender<A>);

/// A `View`s common fields.
pub struct BaseView<S, A> {
@@ -130,6 +130,22 @@ pub trait Properties {
    }
}

+
pub trait WidgetState {
+
    fn to_boxed_any(self) -> Box<dyn Any>
+
    where
+
        Self: Sized + Clone + 'static,
+
    {
+
        Box::new(self)
+
    }
+

+
    fn from_boxed_any(any: Box<dyn Any>) -> Option<Self>
+
    where
+
        Self: Sized + Clone + 'static,
+
    {
+
        any.downcast_ref::<Self>().cloned()
+
    }
+
}
+

#[derive(Clone)]
pub struct WindowProps<Id> {
    current_page: Option<Id>,
@@ -457,6 +473,7 @@ where
}

impl<'a: 'static, R> Properties for TableProps<'a, R> where R: ToRow + 'static {}
+
impl WidgetState for TableState {}

pub struct Table<'a, S, A, R>
where
@@ -570,7 +587,10 @@ where
        self.props.selected = self.state.selected();

        if let Some(on_event) = self.base.on_event {
-
            (on_event)(&self.state, self.base.action_tx.clone());
+
            (on_event)(
+
                self.state.clone().to_boxed_any(),
+
                self.base.action_tx.clone(),
+
            );
        }
    }

modified src/ui/widget/container.rs
@@ -92,11 +92,7 @@ impl<'a: 'static, S, A> Widget for Header<'a, S, A> {
        }
    }

-
    fn handle_event(&mut self, _key: Key) {
-
        if let Some(on_event) = self.base.on_event {
-
            (on_event)(&self.props, self.base.action_tx.clone());
-
        }
-
    }
+
    fn handle_event(&mut self, _key: Key) {}

    fn update(&mut self, state: &S) {
        self.props = self
@@ -269,11 +265,7 @@ impl<'a: 'static, S, A> Widget for Footer<'a, S, A> {
        }
    }

-
    fn handle_event(&mut self, _key: Key) {
-
        if let Some(on_event) = self.base.on_event {
-
            (on_event)(&self.props, self.base.action_tx.clone());
-
        }
-
    }
+
    fn handle_event(&mut self, _key: Key) {}

    fn update(&mut self, state: &S) {
        self.props = self
modified src/ui/widget/input.rs
@@ -9,7 +9,7 @@ use ratatui::prelude::Rect;
use ratatui::style::Stylize;
use ratatui::text::{Line, Span};

-
use super::{BaseView, Properties, Widget};
+
use super::{BaseView, Properties, Widget, WidgetState};

#[derive(Clone)]
pub struct TextFieldProps {
@@ -50,11 +50,15 @@ impl Default for TextFieldProps {
}

impl Properties for TextFieldProps {}
+

+
#[derive(Clone)]
pub struct TextFieldState {
    pub text: Option<String>,
    pub cursor_position: usize,
}

+
impl WidgetState for TextFieldState {}
+

pub struct TextField<S, A> {
    /// Internal base
    base: BaseView<S, A>,
@@ -167,7 +171,10 @@ impl<S, A> Widget for TextField<S, A> {
        }

        if let Some(on_event) = self.base.on_event {
-
            (on_event)(&self.state, self.base.action_tx.clone());
+
            (on_event)(
+
                self.state.clone().to_boxed_any(),
+
                self.base.action_tx.clone(),
+
            );
        }
    }

modified src/ui/widget/text.rs
@@ -7,7 +7,7 @@ use termion::event::Key;
use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::text::Text;

-
use super::{BaseView, Properties, Widget};
+
use super::{BaseView, Properties, Widget, WidgetState};

#[derive(Clone)]
pub struct ParagraphProps<'a> {
@@ -51,6 +51,7 @@ impl<'a> Default for ParagraphProps<'a> {

impl<'a: 'static> Properties for ParagraphProps<'a> {}

+
#[derive(Clone)]
pub struct ParagraphState {
    /// Internal offset
    pub offset: usize,
@@ -58,6 +59,8 @@ pub struct ParagraphState {
    pub progress: usize,
}

+
impl WidgetState for ParagraphState {}
+

pub struct Paragraph<'a, S, A> {
    /// Internal base
    base: BaseView<S, A>,
@@ -190,7 +193,10 @@ impl<'a: 'static, S, A> Widget for Paragraph<'a, S, A> {
        }

        if let Some(on_event) = self.base.on_event {
-
            (on_event)(&self.state, self.base.action_tx.clone());
+
            (on_event)(
+
                self.state.clone().to_boxed_any(),
+
                self.base.action_tx.clone(),
+
            );
        }
    }