use core::fmt::Debug;
use core::marker::PhantomData;
use crate::{MessageContext, MessageResult, Mut, View, ViewMarker, ViewPathTracker};
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct MapMessage<
V,
State,
ParentAction,
ChildAction,
Context,
F = fn(&mut State, ChildAction) -> ParentAction,
> {
map_fn: F,
child: V,
phantom: PhantomData<fn() -> (State, ParentAction, ChildAction, Context)>,
}
impl<V, State, ParentAction, ChildAction, Context, F> Debug
for MapMessage<V, State, ParentAction, ChildAction, Context, F>
where
V: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("MapAction")
.field("child", &self.child)
.finish_non_exhaustive()
}
}
pub fn map_action<State, ParentAction, ChildAction, Context: ViewPathTracker, V, F>(
view: V,
map_fn: F,
) -> MapMessage<
V,
State,
ParentAction,
ChildAction,
Context,
impl Fn(&mut State, MessageResult<ChildAction>) -> MessageResult<ParentAction> + 'static,
>
where
State: 'static,
ParentAction: 'static,
ChildAction: 'static,
V: View<State, ChildAction, Context>,
F: Fn(&mut State, ChildAction) -> ParentAction + 'static,
{
MapMessage {
map_fn: move |app_state: &mut State, result: MessageResult<ChildAction>| {
result.map(|action| map_fn(app_state, action))
},
child: view,
phantom: PhantomData,
}
}
pub fn map_message<State, ParentAction, ChildAction, Context: ViewPathTracker, V, F>(
view: V,
map_fn: F,
) -> MapMessage<V, State, ParentAction, ChildAction, Context, F>
where
State: 'static,
ParentAction: 'static,
ChildAction: 'static,
V: View<State, ChildAction, Context>,
F: Fn(&mut State, MessageResult<ChildAction>) -> MessageResult<ParentAction> + 'static,
{
MapMessage {
map_fn,
child: view,
phantom: PhantomData,
}
}
impl<V, State, ParentAction, ChildAction, F, Context> ViewMarker
for MapMessage<V, State, ParentAction, ChildAction, Context, F>
{
}
impl<V, State, ParentAction, ChildAction, Context, F> View<State, ParentAction, Context>
for MapMessage<V, State, ParentAction, ChildAction, Context, F>
where
V: View<State, ChildAction, Context>,
State: 'static,
ParentAction: 'static,
ChildAction: 'static,
F: Fn(&mut State, MessageResult<ChildAction>) -> MessageResult<ParentAction> + 'static,
Context: ViewPathTracker + 'static,
{
type ViewState = V::ViewState;
type Element = V::Element;
fn build(&self, ctx: &mut Context, app_state: &mut State) -> (Self::Element, Self::ViewState) {
self.child.build(ctx, app_state)
}
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
app_state: &mut State,
) {
self.child
.rebuild(&prev.child, view_state, ctx, element, app_state);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
) {
self.child.teardown(view_state, ctx, element);
}
fn message(
&self,
view_state: &mut Self::ViewState,
message: &mut MessageContext,
element: Mut<'_, Self::Element>,
app_state: &mut State,
) -> MessageResult<ParentAction> {
let child_result = self.child.message(view_state, message, element, app_state);
(self.map_fn)(app_state, child_result)
}
}