use crate::dom_types::{MessageMapper, View};
use crate::vdom::{App, Effect, ShouldRender};
use futures::Future;
use std::{collections::VecDeque, convert::identity, rc::Rc};
pub trait Orders<Ms: 'static, GMs = ()> {
type AppMs: 'static;
type Mdl: 'static;
type ElC: View<Self::AppMs> + 'static;
fn proxy<ChildMs: 'static>(
&mut self,
f: impl FnOnce(ChildMs) -> Ms + 'static + Clone,
) -> OrdersProxy<ChildMs, Self::AppMs, Self::Mdl, Self::ElC, GMs>;
fn render(&mut self) -> &mut Self;
fn force_render_now(&mut self) -> &mut Self;
fn skip(&mut self) -> &mut Self;
fn send_msg(&mut self, msg: Ms) -> &mut Self;
fn perform_cmd<C>(&mut self, cmd: C) -> &mut Self
where
C: Future<Item = Ms, Error = Ms> + 'static;
fn send_g_msg(&mut self, g_msg: GMs) -> &mut Self;
fn perform_g_cmd<C>(&mut self, g_cmd: C) -> &mut Self
where
C: Future<Item = GMs, Error = GMs> + 'static;
fn clone_app(&self) -> App<Self::AppMs, Self::Mdl, Self::ElC, GMs>;
fn msg_mapper(&self) -> Box<dyn Fn(Ms) -> Self::AppMs>;
}
#[allow(clippy::module_name_repetitions)]
pub struct OrdersContainer<Ms: 'static, Mdl: 'static, ElC: View<Ms>, GMs = ()> {
pub(crate) should_render: ShouldRender,
pub(crate) effects: VecDeque<Effect<Ms, GMs>>,
app: App<Ms, Mdl, ElC, GMs>,
}
impl<Ms, Mdl, ElC: View<Ms>, GMs> OrdersContainer<Ms, Mdl, ElC, GMs> {
pub fn new(app: App<Ms, Mdl, ElC, GMs>) -> Self {
Self {
should_render: ShouldRender::Render,
effects: VecDeque::new(),
app,
}
}
}
impl<Ms: 'static, Mdl, ElC: View<Ms> + 'static, GMs> Orders<Ms, GMs>
for OrdersContainer<Ms, Mdl, ElC, GMs>
{
type AppMs = Ms;
type Mdl = Mdl;
type ElC = ElC;
#[allow(clippy::redundant_closure)]
fn proxy<ChildMs: 'static>(
&mut self,
f: impl FnOnce(ChildMs) -> Ms + 'static + Clone,
) -> OrdersProxy<ChildMs, Ms, Mdl, ElC, GMs> {
OrdersProxy::new(self, move |child_ms| f.clone()(child_ms))
}
fn render(&mut self) -> &mut Self {
self.should_render = ShouldRender::Render;
self
}
fn force_render_now(&mut self) -> &mut Self {
self.should_render = ShouldRender::ForceRenderNow;
self
}
fn skip(&mut self) -> &mut Self {
self.should_render = ShouldRender::Skip;
self
}
fn send_msg(&mut self, msg: Ms) -> &mut Self {
self.effects.push_back(msg.into());
self
}
fn perform_cmd<C>(&mut self, cmd: C) -> &mut Self
where
C: Future<Item = Ms, Error = Ms> + 'static,
{
let effect = Effect::Cmd(Box::new(cmd));
self.effects.push_back(effect);
self
}
fn send_g_msg(&mut self, g_msg: GMs) -> &mut Self {
let effect = Effect::GMsg(g_msg);
self.effects.push_back(effect);
self
}
fn perform_g_cmd<C>(&mut self, g_cmd: C) -> &mut Self
where
C: Future<Item = GMs, Error = GMs> + 'static,
{
let effect = Effect::GCmd(Box::new(g_cmd));
self.effects.push_back(effect);
self
}
fn clone_app(&self) -> App<Self::AppMs, Self::Mdl, Self::ElC, GMs> {
self.app.clone()
}
fn msg_mapper(&self) -> Box<dyn Fn(Ms) -> Self::AppMs> {
Box::new(identity)
}
}
#[allow(clippy::module_name_repetitions)]
pub struct OrdersProxy<'a, Ms, AppMs: 'static, Mdl: 'static, ElC: View<AppMs>, GMs: 'static = ()> {
orders_container: &'a mut OrdersContainer<AppMs, Mdl, ElC, GMs>,
f: Rc<dyn Fn(Ms) -> AppMs>,
}
impl<'a, Ms: 'static, AppMs: 'static, Mdl, ElC: View<AppMs>, GMs>
OrdersProxy<'a, Ms, AppMs, Mdl, ElC, GMs>
{
pub fn new(
orders_container: &'a mut OrdersContainer<AppMs, Mdl, ElC, GMs>,
f: impl Fn(Ms) -> AppMs + 'static,
) -> Self {
OrdersProxy {
orders_container,
f: Rc::new(f),
}
}
}
impl<'a, Ms: 'static, AppMs: 'static, Mdl, ElC: View<AppMs> + 'static, GMs> Orders<Ms, GMs>
for OrdersProxy<'a, Ms, AppMs, Mdl, ElC, GMs>
{
type AppMs = AppMs;
type Mdl = Mdl;
type ElC = ElC;
fn proxy<ChildMs: 'static>(
&mut self,
f: impl FnOnce(ChildMs) -> Ms + 'static + Clone,
) -> OrdersProxy<ChildMs, AppMs, Mdl, ElC, GMs> {
let previous_f = self.f.clone();
OrdersProxy {
orders_container: self.orders_container,
f: Rc::new(move |child_ms| previous_f(f.clone()(child_ms))),
}
}
fn render(&mut self) -> &mut Self {
self.orders_container.render();
self
}
fn force_render_now(&mut self) -> &mut Self {
self.orders_container.force_render_now();
self
}
fn skip(&mut self) -> &mut Self {
self.orders_container.skip();
self
}
#[allow(clippy::redundant_closure)]
fn send_msg(&mut self, msg: Ms) -> &mut Self {
let f = self.f.clone();
self.orders_container
.effects
.push_back(Effect::Msg(msg).map_message(move |ms| f(ms)));
self
}
#[allow(clippy::redundant_closure)]
fn perform_cmd<C>(&mut self, cmd: C) -> &mut Self
where
C: Future<Item = Ms, Error = Ms> + 'static,
{
let f = self.f.clone();
let effect = Effect::Cmd(Box::new(cmd)).map_message(move |ms| f(ms));
self.orders_container.effects.push_back(effect);
self
}
fn send_g_msg(&mut self, g_msg: GMs) -> &mut Self {
let effect = Effect::GMsg(g_msg);
self.orders_container.effects.push_back(effect);
self
}
fn perform_g_cmd<C>(&mut self, g_cmd: C) -> &mut Self
where
C: Future<Item = GMs, Error = GMs> + 'static,
{
let effect = Effect::GCmd(Box::new(g_cmd));
self.orders_container.effects.push_back(effect);
self
}
fn clone_app(&self) -> App<Self::AppMs, Self::Mdl, Self::ElC, GMs> {
self.orders_container.clone_app()
}
#[allow(clippy::redundant_closure)]
fn msg_mapper(&self) -> Box<dyn Fn(Ms) -> Self::AppMs> {
let f = self.f.clone();
Box::new(move |ms| f(ms))
}
}