use crate::{prelude::*, render_helper::PureRender};
pub trait RInto<Target, Kind: ?Sized> {
fn r_into(self) -> Target;
}
pub trait RFrom<Source, Kind: ?Sized> {
fn r_from(from: Source) -> Self;
}
pub struct IntoKind;
impl<C, T> RFrom<C, IntoKind> for T
where
C: Into<T>,
{
#[inline]
fn r_from(from: C) -> Self { from.into() }
}
impl<Builder, C, K: ?Sized> RFrom<C, TmlKind<K>> for Builder
where
Builder: TemplateBuilder + ComposeWithChild<C, K, Target = Builder>,
{
fn r_from(from: C) -> Self { Builder::default().with_child(from) }
}
impl<'c, P, C, K> RFrom<Pair<P, C>, K> for Pair<P, Widget<'c>>
where
C: IntoWidget<'c, K>,
K: NotWidgetSelf,
{
fn r_from(from: Pair<P, C>) -> Self {
let (parent, child) = from.unzip();
Pair::new(parent, child.into_widget())
}
}
impl<'c, W, C, K: ?Sized> RFrom<Pair<W, C>, K> for PairOf<'c, W>
where
W: ComposeChild<'c, Child: RFrom<C, K>> + 'static,
{
fn r_from(from: Pair<W, C>) -> Self {
let (parent, child) = from.unzip();
Self(FatObj::new(Pair::new(Stateful::new(parent), child.r_into())))
}
}
impl<'c, W, C, K: ?Sized> RFrom<Pair<Stateful<W>, C>, K> for PairOf<'c, W>
where
W: ComposeChild<'c, Child: RFrom<C, K>> + 'static,
{
fn r_from(from: Pair<Stateful<W>, C>) -> Self {
let (parent, child) = from.unzip();
Self(FatObj::new(Pair::new(parent, child.r_into())))
}
}
impl<'c, W, C, K: ?Sized> RFrom<FatObj<Pair<Stateful<W>, C>>, K> for PairOf<'c, W>
where
W: ComposeChild<'c, Child: RFrom<C, K>> + 'static,
{
fn r_from(from: FatObj<Pair<Stateful<W>, C>>) -> Self {
let pair = from.map(|p| {
let (parent, child) = p.unzip();
Pair::new(parent, child.r_into())
});
Self(pair)
}
}
pub struct PipeOptionWidget<K: ?Sized>(PhantomData<fn() -> K>);
pub struct OtherWidget<K: ?Sized>(PhantomData<fn() -> K>);
pub(crate) trait NotWidgetSelf {}
impl<K: ?Sized> NotWidgetSelf for OtherWidget<K> {}
impl<K: ?Sized> NotWidgetSelf for PipeOptionWidget<K> {}
impl<C: Compose + 'static> RFrom<C, OtherWidget<dyn Compose>> for Widget<'static> {
fn r_from(widget: C) -> Self { Compose::compose(Stateful::new(widget)) }
}
impl<W: StateWriter<Value: Compose + Sized>>
RFrom<W, OtherWidget<dyn StateWriter<Value = &dyn Compose>>> for Widget<'static>
{
fn r_from(widget: W) -> Self { Compose::compose(widget) }
}
impl<R: Render + 'static> RFrom<R, OtherWidget<dyn Render>> for Widget<'static> {
fn r_from(widget: R) -> Self { Widget::from_render(Box::new(PureRender(widget))) }
}
struct ReaderRender<T>(T);
impl<R: StateReader<Value: Render>> crate::render_helper::RenderProxy for ReaderRender<R> {
#[inline(always)]
fn proxy(&self) -> impl Deref<Target = impl Render + ?Sized> { self.0.read() }
}
macro_rules! impl_into_x_widget_for_state_reader {
(<$($generics:ident $(: $bounds:ident)?),* > $ty:ty $(where $($t: tt)*)?) => {
impl<$($generics $(:$bounds)?,)*> RFrom<$ty, OtherWidget<dyn Render>> for Widget<'static>
$(where $($t)*)?
{
fn r_from(widget: $ty) -> Self {
match widget.try_into_value() {
Ok(value) => value.into_widget(),
Err(s) => {
ReaderRender(s).into_widget()
},
}
}
}
};
}
macro_rules! impl_into_x_widget_for_state_watcher {
(<$($generics:ident $(: $bounds:ident)?),* > $ty:ty $(where $($t: tt)*)?) => {
impl<$($generics $(:$bounds)?,)*> RFrom<$ty, OtherWidget<dyn Render>> for Widget<'static>
$(where $($t)*)?
{
fn r_from(widget: $ty) -> Self {
match widget.try_into_value() {
Ok(value) => value.into_widget(),
Err(s) => {
let modifies = s.raw_modifies();
ReaderRender(s.clone_reader())
.into_widget()
.dirty_on(modifies, s.read().dirty_phase())
},
}
}
}
};
}
impl_into_x_widget_for_state_reader!(<R: Render> Box<dyn StateReader<Value = R>>);
impl_into_x_widget_for_state_reader!(
<O, M> PartReader<O, M>
where PartReader<O, M>: StateReader<Value: Render + Sized>
);
impl_into_x_widget_for_state_watcher!(<R: Render> Stateful<R>);
impl_into_x_widget_for_state_watcher!(
<W, WM> PartWriter<W, WM>
where PartWriter<W, WM>: StateWatcher<Value: Render + Sized>
);
impl<'w, F, W, K> RFrom<F, OtherWidget<dyn FnOnce() -> K>> for Widget<'w>
where
F: FnOnce() -> W + 'w,
W: IntoWidget<'w, K> + 'w,
{
#[inline]
fn r_from(value: F) -> Self { Widget::from_fn(move |ctx| value().into_widget().call(ctx)) }
}
impl<'w, F, W, K> RFrom<FnWidget<W, F>, OtherWidget<dyn FnOnce() -> K>> for Widget<'w>
where
F: FnOnce() -> W + 'w,
W: IntoWidget<'w, K> + 'w,
{
#[inline]
fn r_from(value: FnWidget<W, F>) -> Self { value.0.into_widget() }
}
impl<F, W, K> RFrom<FnWidget<W, F>, dyn FnOnce() -> K> for GenWidget
where
F: FnMut() -> W + 'static,
W: IntoWidget<'static, K>,
{
#[inline]
fn r_from(value: FnWidget<W, F>) -> Self { GenWidget::from_fn_widget(value) }
}
impl<F, W, K> RFrom<F, dyn FnOnce() -> K> for GenWidget
where
F: FnMut() -> W + 'static,
W: IntoWidget<'static, K>,
{
#[inline]
fn r_from(value: F) -> Self { GenWidget::new(value) }
}
impl<W, K> RFrom<Box<dyn FnMut() -> W>, K> for GenWidget
where
W: IntoWidget<'static, K> + 'static,
{
#[inline]
fn r_from(value: Box<dyn FnMut() -> W>) -> Self { GenWidget::new(value) }
}
impl<'w, T, K> RFrom<FatObj<T>, OtherWidget<FatObj<K>>> for Widget<'w>
where
T: IntoWidget<'w, K>,
{
fn r_from(value: FatObj<T>) -> Self { value.map(|w| w.into_widget()).compose() }
}
impl<P, K> RFrom<Pipe<P>, OtherWidget<Pipe<fn() -> K>>> for Widget<'static>
where
P: RInto<Widget<'static>, K> + 'static,
{
fn r_from(pipe: Pipe<P>) -> Self { pipe.build_single() }
}
impl<P, K> RFrom<Pipe<Option<P>>, PipeOptionWidget<K>> for Widget<'static>
where
P: RInto<Widget<'static>, K> + 'static,
{
fn r_from(pipe: Pipe<Option<P>>) -> Self { pipe.build_single() }
}
impl<C, T, K: ?Sized> RInto<C, K> for T
where
C: RFrom<T, K>,
{
fn r_into(self) -> C { C::r_from(self) }
}