pub use chargrid_input;
pub use chargrid_input::Input;
pub use chargrid_render;
pub use chargrid_render::{ColModify, Frame, View, ViewContext};
use std::marker::PhantomData;
use std::time::Duration;
mod app;
pub mod common_event;
pub use app::*;
pub enum Handled<R, C> {
Return(R),
Continue(C),
}
impl<R, C> Handled<R, C> {
pub fn map_continue<D, F>(self, f: F) -> Handled<R, D>
where
F: FnOnce(C) -> D,
{
match self {
Handled::Return(r) => Handled::Return(r),
Handled::Continue(c) => Handled::Continue(f(c)),
}
}
pub fn map_return<S, F>(self, f: F) -> Handled<S, C>
where
F: FnOnce(R) -> S,
{
match self {
Handled::Return(r) => Handled::Return(f(r)),
Handled::Continue(c) => Handled::Continue(c),
}
}
}
pub trait EventOrPeek: Sized + private::Sealed {
type Event;
fn with<A, X, F, G>(self, arg: A, f: F, g: G) -> X
where
F: FnOnce(A, Self::Event) -> X,
G: FnOnce(A) -> X;
}
pub fn event_or_peek_with_handled<EP, A, X, F>(event_or_peek: EP, arg: A, f: F) -> Handled<X, A>
where
EP: EventOrPeek,
F: FnOnce(A, EP::Event) -> Handled<X, A>,
{
event_or_peek.with(arg, f, Handled::Continue)
}
pub struct Event<E>(E);
pub struct Peek<E>(PhantomData<E>);
impl<E> Event<E> {
pub fn new(e: E) -> Self {
Self(e)
}
}
impl<E> Peek<E> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<E> Default for Peek<E> {
fn default() -> Self {
Self::new()
}
}
impl<E> EventOrPeek for Event<E> {
type Event = E;
fn with<A, X, F, G>(self, arg: A, f: F, _g: G) -> X
where
F: FnOnce(A, Self::Event) -> X,
G: FnOnce(A) -> X,
{
f(arg, self.0)
}
}
impl<E> EventOrPeek for Peek<E> {
type Event = E;
fn with<A, X, F, G>(self, arg: A, _f: F, g: G) -> X
where
F: FnOnce(A, Self::Event) -> X,
G: FnOnce(A) -> X,
{
g(arg)
}
}
mod private {
pub trait Sealed {}
impl<E> Sealed for super::Event<E> {}
impl<E> Sealed for super::Peek<E> {}
}
pub trait EventRoutine: Sized {
type Return;
type Data;
type View;
type Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>;
fn view<F, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut F,
) where
F: Frame,
C: ColModify;
fn repeat<U, F>(self, f: F) -> Repeat<Self, F>
where
F: FnMut(Self::Return) -> Handled<U, Self>,
{
Repeat { t: self, f }
}
fn select<S>(self, selector: S) -> Select<Self, S>
where
S: Selector<DataOutput = Self::Data, ViewOutput = Self::View>,
{
Select { t: self, selector }
}
fn then<U, F>(self, f: F) -> Then<Self, U, F>
where
U: EventRoutine<Data = Self::Data, View = Self::View>,
F: FnOnce() -> U,
{
Then(AndThenPrivate::First { t: self, f })
}
fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
where
U: EventRoutine<Data = Self::Data, View = Self::View>,
F: FnOnce(Self::Return) -> U,
{
AndThen(AndThenPrivate::First { t: self, f })
}
fn map<F, U>(self, f: F) -> Map<Self, F>
where
F: FnOnce(Self::Return) -> U,
{
Map { t: self, f }
}
fn convert_input_to_common_event(self) -> common_event::ConvertInputToCommonEvent<Self> {
common_event::ConvertInputToCommonEvent(self)
}
fn app_one_shot_ignore_return(
self,
data: Self::Data,
view: Self::View,
) -> EventRoutineAppOneShotIgnoreReturn<Self> {
EventRoutineAppOneShotIgnoreReturn::new(self, data, view)
}
fn return_on_exit<F>(self, f: F) -> common_event::ReturnOnExit<Self, F>
where
F: FnOnce(&mut Self::Data) -> Self::Return,
{
common_event::ReturnOnExit { t: self, f }
}
fn decorated<D>(self, d: D) -> Decorated<Self, D>
where
D: Decorate<View = Self::View, Data = Self::Data>,
{
Decorated { t: self, d }
}
fn on_event<F>(self, f: F) -> OnEvent<Self, F>
where
F: FnMut(&mut &mut Self::Data, &Self::Event),
{
OnEvent { t: self, f }
}
}
struct OneShot<T, D, V, E> {
field: T,
data: PhantomData<D>,
view: PhantomData<V>,
event: PhantomData<E>,
}
impl<T, D, V, E> OneShot<T, D, V, E> {
pub fn new(field: T) -> Self {
Self {
field,
data: PhantomData,
view: PhantomData,
event: PhantomData,
}
}
}
pub struct Value<T, D, V, E>(OneShot<T, D, V, E>);
impl<T, D, V, E> Value<T, D, V, E> {
pub fn new(value: T) -> Self {
Self(OneShot::new(value))
}
}
impl<T, D, V, E> EventRoutine for Value<T, D, V, E> {
type Return = T;
type Data = D;
type View = V;
type Event = E;
fn handle<EP>(
self,
_data: &mut Self::Data,
_view: &Self::View,
_event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
Handled::Return(self.0.field)
}
fn view<F, C>(
&self,
_data: &Self::Data,
_view: &mut Self::View,
_context: ViewContext<C>,
_frame: &mut F,
) where
F: Frame,
C: ColModify,
{
}
}
pub struct SideEffect<F, D, V, E>(OneShot<F, D, V, E>);
impl<F, D, V, E> SideEffect<F, D, V, E> {
pub fn new_with_view(f: F) -> Self {
Self(OneShot::new(f))
}
}
pub fn side_effect_with_view<F, D, V, E, T>(
f: F,
) -> impl EventRoutine<Return = T, Data = D, View = V, Event = E>
where
F: FnOnce(&mut D, &V) -> T,
{
SideEffect::new_with_view(f)
}
pub fn side_effect<F, D, V, E, T>(
f: F,
) -> impl EventRoutine<Return = T, Data = D, View = V, Event = E>
where
F: FnOnce(&mut D) -> T,
{
side_effect_with_view(|data: &mut D, _view: &V| f(data))
}
impl<F, D, V, E, T> EventRoutine for SideEffect<F, D, V, E>
where
F: FnOnce(&mut D, &V) -> T,
{
type Return = T;
type Data = D;
type View = V;
type Event = E;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
_event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
Handled::Return((self.0.field)(data, view))
}
fn view<G, C>(
&self,
_data: &Self::Data,
_view: &mut Self::View,
_context: ViewContext<C>,
_frame: &mut G,
) where
G: Frame,
C: ColModify,
{
}
}
enum SideEffectThenPrivate<F, D, V, E, U> {
First(OneShot<F, D, V, E>),
Second(U),
}
pub struct SideEffectThen<F, D, V, E, U>(SideEffectThenPrivate<F, D, V, E, U>);
impl<F, D, V, E, U> SideEffectThen<F, D, V, E, U>
where
U: EventRoutine<Data = D, View = V, Event = E>,
F: FnOnce(&mut D, &V) -> U,
{
pub fn new_with_view(f: F) -> Self {
Self(SideEffectThenPrivate::First(OneShot::new(f)))
}
}
pub fn side_effect_then_with_view<F, D, V, U>(
f: F,
) -> impl EventRoutine<Return = U::Return, Data = U::Data, View = U::View, Event = U::Event>
where
U: EventRoutine<Data = D, View = V>,
F: FnOnce(&mut D, &V) -> U,
{
SideEffectThen::new_with_view(f)
}
pub fn side_effect_then<F, D, V, U>(
f: F,
) -> impl EventRoutine<Return = U::Return, Data = U::Data, View = U::View, Event = U::Event>
where
U: EventRoutine<Data = D, View = V>,
F: FnOnce(&mut D) -> U,
{
side_effect_then_with_view(|data: &mut D, _view: &V| f(data))
}
impl<F, D, V, E, U> EventRoutine for SideEffectThen<F, D, V, E, U>
where
U: EventRoutine<Data = D, View = V, Event = E>,
F: FnOnce(&mut D, &V) -> U,
{
type Return = U::Return;
type Data = D;
type View = V;
type Event = E;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
match self.0 {
SideEffectThenPrivate::First(one_shot) => (one_shot.field)(data, view)
.handle(data, view, Peek::new())
.map_continue(|u| SideEffectThen(SideEffectThenPrivate::Second(u))),
SideEffectThenPrivate::Second(u) => u
.handle(data, view, event_or_peek)
.map_continue(|u| SideEffectThen(SideEffectThenPrivate::Second(u))),
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
match self.0 {
SideEffectThenPrivate::First(_) => (),
SideEffectThenPrivate::Second(ref u) => u.view(data, view, context, frame),
}
}
}
pub struct Map<T, F> {
t: T,
f: F,
}
impl<T, U, F> EventRoutine for Map<T, F>
where
T: EventRoutine,
F: FnOnce(T::Return) -> U,
{
type Return = U;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self { t, f } = self;
match t.handle(data, view, event_or_peek) {
Handled::Continue(t) => Handled::Continue(Self { t, f }),
Handled::Return(r) => Handled::Return(f(r)),
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
self.t.view(data, view, context, frame)
}
}
enum AndThenPrivate<T, U, F> {
First { t: T, f: F },
Second(U),
}
pub struct Then<T, U, F>(AndThenPrivate<T, U, F>);
impl<T, U, F> EventRoutine for Then<T, U, F>
where
T: EventRoutine,
U: EventRoutine<Data = T::Data, View = T::View, Event = T::Event>,
F: FnOnce() -> U,
{
type Return = U::Return;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
match self.0 {
AndThenPrivate::First { t, f } => match t.handle(data, view, event_or_peek) {
Handled::Continue(t) => Handled::Continue(Self(AndThenPrivate::First { t, f })),
Handled::Return(_) => f()
.handle(data, view, Peek::new())
.map_continue(|u| Self(AndThenPrivate::Second(u))),
},
AndThenPrivate::Second(u) => u
.handle(data, view, event_or_peek)
.map_continue(|u| Self(AndThenPrivate::Second(u))),
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
match self.0 {
AndThenPrivate::First { ref t, .. } => t.view(data, view, context, frame),
AndThenPrivate::Second(ref u) => u.view(data, view, context, frame),
}
}
}
pub struct AndThen<T, U, F>(AndThenPrivate<T, U, F>);
impl<T, U, F> EventRoutine for AndThen<T, U, F>
where
T: EventRoutine,
U: EventRoutine<Data = T::Data, View = T::View, Event = T::Event>,
F: FnOnce(T::Return) -> U,
{
type Return = U::Return;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
match self.0 {
AndThenPrivate::First { t, f } => match t.handle(data, view, event_or_peek) {
Handled::Continue(t) => Handled::Continue(Self(AndThenPrivate::First { t, f })),
Handled::Return(r) => f(r)
.handle(data, view, Peek::new())
.map_continue(|u| Self(AndThenPrivate::Second(u))),
},
AndThenPrivate::Second(u) => u
.handle(data, view, event_or_peek)
.map_continue(|u| Self(AndThenPrivate::Second(u))),
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
match self.0 {
AndThenPrivate::First { ref t, .. } => t.view(data, view, context, frame),
AndThenPrivate::Second(ref u) => u.view(data, view, context, frame),
}
}
}
pub trait DataSelector {
type DataInput;
type DataOutput;
fn data<'a>(&self, input: &'a Self::DataInput) -> &'a Self::DataOutput;
fn data_mut<'a>(&self, input: &'a mut Self::DataInput) -> &'a mut Self::DataOutput;
}
pub trait ViewSelector {
type ViewInput;
type ViewOutput;
fn view<'a>(&self, input: &'a Self::ViewInput) -> &'a Self::ViewOutput;
fn view_mut<'a>(&self, input: &'a mut Self::ViewInput) -> &'a mut Self::ViewOutput;
}
pub trait Selector: DataSelector + ViewSelector {}
#[derive(Clone, Copy)]
pub struct Select<T, S> {
t: T,
selector: S,
}
impl<T, S> EventRoutine for Select<T, S>
where
T: EventRoutine,
S: Selector<DataOutput = T::Data, ViewOutput = T::View>,
{
type Return = T::Return;
type Data = S::DataInput;
type View = S::ViewInput;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self { t, selector } = self;
t.handle(selector.data_mut(data), selector.view(view), event_or_peek)
.map_continue(|t| Self { t, selector })
}
fn view<F, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut F,
) where
F: Frame,
C: ColModify,
{
self.t.view(
self.selector.data(data),
self.selector.view_mut(view),
context,
frame,
)
}
}
pub struct Repeat<T, F> {
t: T,
f: F,
}
impl<T, U, F> EventRoutine for Repeat<T, F>
where
T: EventRoutine,
F: FnMut(T::Return) -> Handled<U, T>,
{
type Return = U;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self { t, mut f } = self;
match t.handle(data, view, event_or_peek) {
Handled::Continue(t) => Handled::Continue(Self { t, f }),
Handled::Return(r) => match f(r) {
Handled::Continue(t) => Handled::Continue(Self { t, f }),
Handled::Return(r) => Handled::Return(r),
},
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
self.t.view(data, view, context, frame)
}
}
pub struct EventRoutineView<'e, 'v, E: EventRoutine> {
pub event_routine: &'e E,
pub view: &'v mut E::View,
}
impl<'e, 'v, 'd, E> View<&'d E::Data> for EventRoutineView<'e, 'v, E>
where
E: EventRoutine,
{
fn view<F: Frame, C: ColModify>(
&mut self,
data: &'d E::Data,
context: ViewContext<C>,
frame: &mut F,
) {
self.event_routine.view(data, self.view, context, frame)
}
}
pub trait Decorate {
type View;
type Data;
fn view<E, F, C>(
&self,
data: &Self::Data,
event_routine_view: EventRoutineView<E>,
context: ViewContext<C>,
frame: &mut F,
) where
E: EventRoutine<Data = Self::Data, View = Self::View>,
F: Frame,
C: ColModify;
}
pub struct Decorated<T, D> {
t: T,
d: D,
}
impl<T, D> EventRoutine for Decorated<T, D>
where
T: EventRoutine,
D: Decorate<View = T::View, Data = T::Data>,
{
type Return = T::Return;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self { t, d } = self;
t.handle(data, view, event_or_peek)
.map_continue(|t| Self { t, d })
}
fn view<F, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut F,
) where
F: Frame,
C: ColModify,
{
let event_routine_view = EventRoutineView {
event_routine: &self.t,
view,
};
self.d.view(data, event_routine_view, context, frame)
}
}
pub struct OnEvent<T, F> {
t: T,
f: F,
}
impl<T, F> EventRoutine for OnEvent<T, F>
where
T: EventRoutine,
F: FnMut(&mut &mut T::Data, &T::Event),
{
type Return = T::Return;
type Data = T::Data;
type View = T::View;
type Event = T::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let on_peek = |(s, data)| {
let Self { t, f } = s;
t.handle(data, view, Peek::new())
.map_continue(|t| Self { t, f })
};
let on_event = |(s, mut data), event| {
let Self { t, mut f } = s;
(f)(&mut data, &event);
t.handle(data, view, Event::new(event))
.map_continue(|t| Self { t, f })
};
event_or_peek.with((self, data), on_event, on_peek)
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
self.t.view(data, view, context, frame);
}
}
pub struct Unfold<T, U, F, R> {
t: PhantomData<T>,
u: PhantomData<U>,
f: F,
routine: R,
}
impl<T, U, F, R> Unfold<T, U, F, R>
where
F: FnMut(T) -> R,
R: EventRoutine<Return = Handled<U, T>>,
{
pub fn new(acc: T, mut f: F) -> Self {
let routine = f(acc);
Self {
f,
routine,
t: PhantomData,
u: PhantomData,
}
}
}
impl<T, U, F, R> EventRoutine for Unfold<T, U, F, R>
where
F: FnMut(T) -> R,
R: EventRoutine<Return = Handled<U, T>>,
{
type Return = U;
type Data = R::Data;
type View = R::View;
type Event = R::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self {
t,
u,
mut f,
routine,
} = self;
match routine.handle(data, view, event_or_peek) {
Handled::Continue(routine) => Handled::Continue(Self { t, u, f, routine }),
Handled::Return(handled) => match handled {
Handled::Continue(acc) => Handled::Continue(Self {
t,
u,
routine: f(acc),
f,
}),
Handled::Return(ret) => Handled::Return(ret),
},
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
self.routine.view(data, view, context, frame)
}
}
pub struct Loop<T, F, R> {
t: PhantomData<T>,
f: F,
routine: R,
}
impl<T, F, R> Loop<T, F, R>
where
F: FnMut() -> R,
R: EventRoutine<Return = Option<T>>,
{
pub fn new(mut f: F) -> Self {
let routine = f();
Self {
t: PhantomData,
f,
routine,
}
}
}
impl<T, F, R> EventRoutine for Loop<T, F, R>
where
F: FnMut() -> R,
R: EventRoutine<Return = Option<T>>,
{
type Return = T;
type Data = R::Data;
type View = R::View;
type Event = R::Event;
fn handle<EP>(
self,
data: &mut Self::Data,
view: &Self::View,
event_or_peek: EP,
) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
let Self { t, mut f, routine } = self;
match routine.handle(data, view, event_or_peek) {
Handled::Continue(routine) => Handled::Continue(Self { t, f, routine }),
Handled::Return(maybe_ret) => match maybe_ret {
None => Handled::Continue(Self { t, routine: f(), f }),
Some(ret) => Handled::Return(ret),
},
}
}
fn view<G, C>(
&self,
data: &Self::Data,
view: &mut Self::View,
context: ViewContext<C>,
frame: &mut G,
) where
G: Frame,
C: ColModify,
{
self.routine.view(data, view, context, frame)
}
}
#[macro_export]
macro_rules! make_either {
($type:ident = $first:ident | $($rest:ident)|*) => {
pub enum $type<$first, $($rest),*> {
$first($first),
$($rest($rest)),*
}
impl<$first, $($rest),*> EventRoutine for $type<$first, $($rest),*>
where
$first: EventRoutine,
$($rest: EventRoutine<Data = $first::Data, View = $first::View, Return = $first::Return, Event = $first::Event>),*
{
type Return = $first::Return;
type Data = $first::Data;
type View = $first::View;
type Event = $first::Event;
fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
where
EP: EventOrPeek<Event = Self::Event>,
{
match self {
$type::$first(x) => x.handle(data, view, event_or_peek).map_continue($type::$first),
$($type::$rest(x) => x.handle(data, view, event_or_peek).map_continue($type::$rest)),*
}
}
fn view<FR, CM>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<CM>, frame: &mut FR)
where
FR: Frame,
CM: ColModify,
{
match self {
$type::$first(x) => x.view(data, view, context, frame),
$($type::$rest(x) => x.view(data, view, context, frame)),*
}
}
}
};
}