use chargrid_core::{Component, Ctx, Event, FrameBuffer, UCoord};
use std::marker::PhantomData;
mod boxed;
mod unboxed;
pub use boxed::*;
pub trait Lens {
type Input;
type Output;
fn get<'a>(&self, input: &'a Self::Input) -> &'a Self::Output;
fn get_mut<'a>(&mut self, input: &'a mut Self::Input) -> &'a mut Self::Output;
}
pub struct LensFns<I, O, R, M> {
input: PhantomData<I>,
output: PhantomData<O>,
get: R,
get_mut: M,
}
impl<I, O, R, M> LensFns<I, O, R, M> {
pub fn new(get: R, get_mut: M) -> Self {
Self {
input: PhantomData,
output: PhantomData,
get,
get_mut,
}
}
}
impl<I, O, R, M> Lens for LensFns<I, O, R, M>
where
R: Fn(&I) -> &O,
M: FnMut(&mut I) -> &mut O,
{
type Input = I;
type Output = O;
fn get<'a>(&self, input: &'a Self::Input) -> &'a Self::Output {
(self.get)(input)
}
fn get_mut<'a>(&mut self, input: &'a mut Self::Input) -> &'a mut Self::Output {
(self.get_mut)(input)
}
}
pub struct LensState<S, L, C>
where
C: Component,
L: Lens<Input = S, Output = C::State>,
{
state: PhantomData<S>,
lens: L,
component: C,
}
impl<S, L, C> Component for LensState<S, L, C>
where
C: Component,
L: Lens<Input = S, Output = C::State>,
{
type Output = C::Output;
type State = S;
fn render(&self, state: &Self::State, ctx: Ctx, fb: &mut FrameBuffer) {
self.component.render(self.lens.get(state), ctx, fb);
}
fn update(&mut self, state: &mut Self::State, ctx: Ctx, event: Event) -> Self::Output {
self.component.update(self.lens.get_mut(state), ctx, event)
}
fn size(&self, state: &Self::State, ctx: Ctx) -> UCoord {
self.component.size(self.lens.get(state), ctx)
}
}
#[derive(Clone, Copy, Debug)]
pub enum LoopControl<Co, Br> {
Continue(Co),
Break(Br),
}
impl<Co, Br> LoopControl<Co, Br> {
pub fn map_continue<Co2, F: FnOnce(Co) -> Co2>(self, f: F) -> LoopControl<Co2, Br> {
match self {
Self::Continue(co) => LoopControl::Continue(f(co)),
Self::Break(br) => LoopControl::Break(br),
}
}
pub fn map_break<Br2, F: FnOnce(Br) -> Br2>(self, f: F) -> LoopControl<Co, Br2> {
match self {
Self::Continue(co) => LoopControl::Continue(co),
Self::Break(br) => LoopControl::Break(f(br)),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Close;
pub type OrClose<T> = Result<T, Close>;
#[derive(Clone, Copy, Debug)]
pub struct Escape;
pub type OrEscape<T> = Result<T, Escape>;
#[derive(Clone, Copy, Debug)]
pub enum EscapeOrStart {
Escape,
Start,
}
pub type OrEscapeOrStart<T> = Result<T, EscapeOrStart>;
#[derive(Clone, Copy, Debug)]
pub struct ClickOut;
pub type OrClickOut<T> = Result<T, ClickOut>;
#[derive(Clone, Copy, Debug)]
pub enum EscapeOrClickOut {
Escape,
ClickOut,
}
pub type OrEscapeOrClickOut<T> = Result<T, EscapeOrClickOut>;
#[macro_export]
macro_rules! lens {
($input:ty[$field:ident]: $output:ty) => {{
fn get(state: &$input) -> &$output {
&state.$field
}
fn get_mut(state: &mut $input) -> &mut $output {
&mut state.$field
}
LensFns::new(get, get_mut)
}};
}
#[macro_export]
macro_rules! many {
($($items:expr),* $(,)* ) => {
$crate::control_flow::many([
$($crate::control_flow::cf($items)),*
])
};
}
pub use crate::{lens, many};