use core::any::type_name;
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 Lens<CF, V, F, ParentState, ChildState, Action, Context> {
access_state: F,
child_component: CF,
phantom: PhantomData<fn(ParentState) -> (ChildState, Action, Context, V)>,
}
impl<CF, V, F, ParentState, ChildState, Action, Context> Debug
for Lens<CF, V, F, ParentState, ChildState, Action, Context>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Lens")
.field("from", &type_name::<ParentState>())
.field("to", &type_name::<ChildState>())
.finish_non_exhaustive()
}
}
pub fn lens<OuterState, Action, Context, InnerState, StateF, InnerView, Component>(
component: Component,
access_state: StateF,
) -> Lens<Component, InnerView, StateF, OuterState, InnerState, Action, Context>
where
StateF: Fn(&mut OuterState) -> &mut InnerState + Send + Sync + 'static,
Component: Fn(&mut InnerState) -> InnerView,
InnerView: View<InnerState, Action, Context>,
Context: ViewPathTracker,
{
Lens {
child_component: component,
access_state,
phantom: PhantomData,
}
}
impl<Component, V, StateF, ParentState, ChildState, Action, Context> ViewMarker
for Lens<Component, V, StateF, ParentState, ChildState, Action, Context>
{
}
impl<Component, ParentState, ChildState, Action, Context, V, StateF>
View<ParentState, Action, Context>
for Lens<Component, V, StateF, ParentState, ChildState, Action, Context>
where
ParentState: 'static,
ChildState: 'static,
V: View<ChildState, Action, Context>,
Component: Fn(&mut ChildState) -> V + 'static,
StateF: Fn(&mut ParentState) -> &mut ChildState + 'static,
Action: 'static,
Context: ViewPathTracker + 'static,
{
type ViewState = (V, V::ViewState);
type Element = V::Element;
fn build(
&self,
ctx: &mut Context,
app_state: &mut ParentState,
) -> (Self::Element, Self::ViewState) {
let child_state = (self.access_state)(app_state);
let child = (self.child_component)(child_state);
let (element, child_state) = child.build(ctx, (self.access_state)(app_state));
(element, (child, child_state))
}
fn rebuild(
&self,
_prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
app_state: &mut ParentState,
) {
let child_state = (self.access_state)(app_state);
let child = (self.child_component)(child_state);
child.rebuild(&view_state.0, &mut view_state.1, ctx, element, child_state);
view_state.0 = child;
}
fn teardown(
&self,
(child, child_view_state): &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
) {
child.teardown(child_view_state, ctx, element);
}
fn message(
&self,
(child, child_view_state): &mut Self::ViewState,
message: &mut MessageContext,
element: Mut<'_, Self::Element>,
app_state: &mut ParentState,
) -> MessageResult<Action> {
child.message(
child_view_state,
message,
element,
(self.access_state)(app_state),
)
}
}