lib: Improve update callback prorperties

This commit is contained in:
Erik Kundt
2024-04-22 10:57:32 +02:00
parent 7e1237eb32
commit ec63bc50f6
4 changed files with 67 additions and 58 deletions
+35 -22
View File
@@ -32,7 +32,7 @@ pub trait View<S, A> {
Self: Sized;
/// Should set the optional custom event handler.
fn on_change(self, callback: EventCallback<A>) -> Self
fn on_event(self, callback: EventCallback<A>) -> Self
where
Self: Sized;
@@ -51,12 +51,20 @@ pub trait View<S, A> {
/// 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::<Self>().cloned()
}
fn from_callback<S>(callback: Option<UpdateCallback<S>>, state: &S) -> Option<Self>
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<S, A> {
/// Custom update handler
on_update: Option<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
}
impl<S, A> Shortcuts<S, A> {
@@ -161,12 +178,12 @@ impl<S, A> View<S, A> for Shortcuts<S, A> {
_action_tx: action_tx.clone(),
props: ShortcutsProps::default(),
on_update: None,
on_change: None,
on_event: None,
}
}
fn on_change(mut self, callback: EventCallback<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> Self {
self.on_event = Some(callback);
self
}
@@ -178,10 +195,8 @@ impl<S, A> View<S, A> for Shortcuts<S, A> {
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<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
/// 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<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> 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());
}
}
}
+18 -20
View File
@@ -60,7 +60,7 @@ pub struct Header<'a, S, A> {
/// Custom update handler
on_update: Option<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
}
impl<'a, S, A> Header<'a, S, A> {
@@ -87,7 +87,7 @@ impl<'a: 'static, S, A> View<S, A> 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<S, A> for Header<'a, S, A> {
self
}
fn on_change(mut self, callback: EventCallback<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> Self {
self.on_event = Some(callback);
self
}
@@ -109,8 +109,8 @@ impl<'a: 'static, S, A> View<S, A> 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<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
}
impl<'a, S, A> Footer<'a, S, A> {
@@ -251,7 +251,7 @@ impl<'a: 'static, S, A> View<S, A> 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<S, A> for Footer<'a, S, A> {
self
}
fn on_change(mut self, callback: EventCallback<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> Self {
self.on_event = Some(callback);
self
}
@@ -273,8 +273,8 @@ impl<'a: 'static, S, A> View<S, A> 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<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
/// Container header
header: Option<BoxedWidget<B, S, A>>,
/// 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<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> 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);
+6 -6
View File
@@ -63,7 +63,7 @@ pub struct TextField<S, A> {
/// Custom update handler
on_update: Option<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
/// Internal state
state: TextFieldState,
}
@@ -136,7 +136,7 @@ impl<S, A> View<S, A> for TextField<S, A> {
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<S, A> View<S, A> for TextField<S, A> {
self
}
fn on_change(mut self, callback: EventCallback<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> Self {
self.on_event = Some(callback);
self
}
@@ -188,8 +188,8 @@ impl<S, A> View<S, A> for TextField<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());
}
}
}
+8 -10
View File
@@ -67,7 +67,7 @@ pub struct Paragraph<'a, S, A> {
/// Custom update handler
on_update: Option<UpdateCallback<S>>,
/// Additional custom event handler
on_change: Option<EventCallback<A>>,
on_event: Option<EventCallback<A>>,
/// Internal state
state: ParagraphState,
}
@@ -155,7 +155,7 @@ impl<'a: 'static, S, A> View<S, A> 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<S, A> for Paragraph<'a, S, A> {
}
}
fn on_change(mut self, callback: EventCallback<A>) -> Self {
self.on_change = Some(callback);
fn on_event(mut self, callback: EventCallback<A>) -> Self {
self.on_event = Some(callback);
self
}
@@ -174,10 +174,8 @@ impl<'a: 'static, S, A> View<S, A> 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<S, A> 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());
}
}
}