From ec63bc50f6f2e760199b4fc887fdad93de7e5fa1 Mon Sep 17 00:00:00 2001 From: Erik Kundt Date: Mon, 22 Apr 2024 10:43:28 +0200 Subject: [PATCH] lib: Improve update callback prorperties --- src/ui/widget.rs | 57 +++++++++++++++++++++++--------------- src/ui/widget/container.rs | 38 ++++++++++++------------- src/ui/widget/input.rs | 12 ++++---- src/ui/widget/text.rs | 18 ++++++------ 4 files changed, 67 insertions(+), 58 deletions(-) diff --git a/src/ui/widget.rs b/src/ui/widget.rs index b5e76b83..ba344530 100644 --- a/src/ui/widget.rs +++ b/src/ui/widget.rs @@ -32,7 +32,7 @@ pub trait View { Self: Sized; /// Should set the optional custom event handler. - fn on_change(self, callback: EventCallback) -> Self + fn on_event(self, callback: EventCallback) -> Self where Self: Sized; @@ -51,12 +51,20 @@ pub trait View { /// Should handle key events and call `handle_key_event` on all children. /// - /// After key events have been handled, the custom event handler `on_change` should + /// After key events have been handled, the custom event handler `on_event` should /// be called fn handle_key_event(&mut self, key: Key); - /// Should update internal props by calling the custom update handler `on_update` - /// and call `update` on all children. + /// Should update the internal props of this and all children. + /// + /// Applications are usually defined by app-specific widgets that do know + /// the type of `state`. These can use widgets from the library that do not know the + /// type of `state`. + /// + /// If `on_update` is set, implementators of this function should call it to + /// construct and update the internal props. If it is not set, app widgets can construct + /// prosp directly via their state converters, whereas library widgets can just fallback + /// to their current props. fn update(&mut self, state: &S); } @@ -93,6 +101,15 @@ pub trait Properties { { any.downcast_ref::().cloned() } + + fn from_callback(callback: Option>, state: &S) -> Option + where + Self: Sized + Clone + 'static, + { + callback + .map(|callback| (callback)(state)) + .and_then(|props| Self::from_boxed_any(props)) + } } #[derive(Clone)] @@ -135,7 +152,7 @@ pub struct Shortcuts { /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, } impl Shortcuts { @@ -161,12 +178,12 @@ impl View for Shortcuts { _action_tx: action_tx.clone(), props: ShortcutsProps::default(), on_update: None, - on_change: None, + on_event: None, } } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } @@ -178,10 +195,8 @@ impl View for Shortcuts { fn handle_key_event(&mut self, _key: Key) {} fn update(&mut self, state: &S) { - self.props = self - .on_update - .and_then(|on_update| ShortcutsProps::from_boxed_any((on_update)(state))) - .unwrap_or(self.props.clone()) + self.props = + ShortcutsProps::from_callback(self.on_update, state).unwrap_or(self.props.clone()); } } @@ -335,7 +350,7 @@ where /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, /// Internal selection and offset state state: TableState, } @@ -405,7 +420,7 @@ where props: TableProps::default(), state: TableState::default().with_selected(Some(0)), on_update: None, - on_change: None, + on_event: None, } } @@ -414,16 +429,14 @@ where self } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } fn update(&mut self, state: &S) { - self.props = self - .on_update - .and_then(|on_update| TableProps::<'_, R>::from_boxed_any((on_update)(state))) - .unwrap_or(self.props.clone()); + self.props = + TableProps::<'_, R>::from_callback(self.on_update, state).unwrap_or(self.props.clone()); // TODO: Move to state reducer if let Some(selected) = self.state.selected() { @@ -458,8 +471,8 @@ where self.props.selected = self.state.selected(); - if let Some(on_change) = self.on_change { - (on_change)(&self.state, self.action_tx.clone()); + if let Some(on_event) = self.on_event { + (on_event)(&self.state, self.action_tx.clone()); } } } diff --git a/src/ui/widget/container.rs b/src/ui/widget/container.rs index 39ea2f16..3ac638cb 100644 --- a/src/ui/widget/container.rs +++ b/src/ui/widget/container.rs @@ -60,7 +60,7 @@ pub struct Header<'a, S, A> { /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, } impl<'a, S, A> Header<'a, S, A> { @@ -87,7 +87,7 @@ impl<'a: 'static, S, A> View for Header<'a, S, A> { action_tx: action_tx.clone(), props: HeaderProps::default(), on_update: None, - on_change: None, + on_event: None, } } @@ -96,8 +96,8 @@ impl<'a: 'static, S, A> View for Header<'a, S, A> { self } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } @@ -109,8 +109,8 @@ impl<'a: 'static, S, A> View for Header<'a, S, A> { } fn handle_key_event(&mut self, _key: Key) { - if let Some(on_change) = self.on_change { - (on_change)(&self.props, self.action_tx.clone()); + if let Some(on_event) = self.on_event { + (on_event)(&self.props, self.action_tx.clone()); } } } @@ -224,7 +224,7 @@ pub struct Footer<'a, S, A> { /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, } impl<'a, S, A> Footer<'a, S, A> { @@ -251,7 +251,7 @@ impl<'a: 'static, S, A> View for Footer<'a, S, A> { action_tx: action_tx.clone(), props: FooterProps::default(), on_update: None, - on_change: None, + on_event: None, } } @@ -260,8 +260,8 @@ impl<'a: 'static, S, A> View for Footer<'a, S, A> { self } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } @@ -273,8 +273,8 @@ impl<'a: 'static, S, A> View for Footer<'a, S, A> { } fn handle_key_event(&mut self, _key: Key) { - if let Some(on_change) = self.on_change { - (on_change)(&self.props, self.action_tx.clone()); + if let Some(on_event) = self.on_event { + (on_event)(&self.props, self.action_tx.clone()); } } } @@ -375,7 +375,7 @@ where /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, /// Container header header: Option>, /// Content widget @@ -419,7 +419,7 @@ where content: None, footer: None, on_update: None, - on_change: None, + on_event: None, } } @@ -428,16 +428,14 @@ where self } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } fn update(&mut self, state: &S) { - self.props = self - .on_update - .and_then(|on_update| ContainerProps::from_boxed_any((on_update)(state))) - .unwrap_or(self.props.clone()); + self.props = + ContainerProps::from_callback(self.on_update, state).unwrap_or(self.props.clone()); if let Some(header) = &mut self.header { header.update(state); diff --git a/src/ui/widget/input.rs b/src/ui/widget/input.rs index 8430ee3d..2541096c 100644 --- a/src/ui/widget/input.rs +++ b/src/ui/widget/input.rs @@ -63,7 +63,7 @@ pub struct TextField { /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, /// Internal state state: TextFieldState, } @@ -136,7 +136,7 @@ impl View for TextField { action_tx, props: TextFieldProps::default(), on_update: None, - on_change: None, + on_event: None, state: TextFieldState { text: None, cursor_position: 0, @@ -149,8 +149,8 @@ impl View for TextField { self } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } @@ -188,8 +188,8 @@ impl View for TextField { _ => {} } - if let Some(on_change) = self.on_change { - (on_change)(&self.state, self.action_tx.clone()); + if let Some(on_event) = self.on_event { + (on_event)(&self.state, self.action_tx.clone()); } } } diff --git a/src/ui/widget/text.rs b/src/ui/widget/text.rs index c7bb92de..a9f1743e 100644 --- a/src/ui/widget/text.rs +++ b/src/ui/widget/text.rs @@ -67,7 +67,7 @@ pub struct Paragraph<'a, S, A> { /// Custom update handler on_update: Option>, /// Additional custom event handler - on_change: Option>, + on_event: Option>, /// Internal state state: ParagraphState, } @@ -155,7 +155,7 @@ impl<'a: 'static, S, A> View for Paragraph<'a, S, A> { action_tx: action_tx.clone(), props: ParagraphProps::default(), on_update: None, - on_change: None, + on_event: None, state: ParagraphState { offset: 0, progress: 0, @@ -163,8 +163,8 @@ impl<'a: 'static, S, A> View for Paragraph<'a, S, A> { } } - fn on_change(mut self, callback: EventCallback) -> Self { - self.on_change = Some(callback); + fn on_event(mut self, callback: EventCallback) -> Self { + self.on_event = Some(callback); self } @@ -174,10 +174,8 @@ impl<'a: 'static, S, A> View for Paragraph<'a, S, A> { } fn update(&mut self, state: &S) { - self.props = self - .on_update - .and_then(|on_update| ParagraphProps::from_boxed_any((on_update)(state))) - .unwrap_or(self.props.clone()); + self.props = + ParagraphProps::from_callback(self.on_update, state).unwrap_or(self.props.clone()); } fn handle_key_event(&mut self, key: Key) { @@ -206,8 +204,8 @@ impl<'a: 'static, S, A> View for Paragraph<'a, S, A> { _ => {} } - if let Some(on_change) = self.on_change { - (on_change)(&self.state, self.action_tx.clone()); + if let Some(on_event) = self.on_event { + (on_event)(&self.state, self.action_tx.clone()); } } }