use crate::*; use std::sync::RwLock; impl Layout for E {} pub trait Layout { /// Content `item` when `cond` is true. fn when > (cond: bool, item: A) -> When { When(cond, item, Default::default()) } /// Content `item` if `cond` is true, otherwise render `other`. fn either , B: Content> (cond: bool, a: A, b: B) -> Either { Either(cond, a, b, Default::default()) } /// Maps an [Option] through a callback `F` fn opt R, R: Content> (option: Option, cb: F) -> Opt { Opt(option, cb, Default::default()) } fn map (iterator: J, callback: F) -> Map where E: Engine, I: Iterator + Send + Sync, J: Fn() -> I + Send + Sync, R: Content, F: Fn(T, usize)->R + Send + Sync { Map(Default::default(), iterator, callback) } //pub fn reduce (iterator: I, callback: F) -> Reduce where //E: Engine, //I: Iterator + Send + Sync, //R: Content, //F: Fn(R, T, usize) -> R + Send + Sync //{ //Reduce(Default::default(), iterator, callback) //} } pub struct OptR, R: Content>(Option, F, PhantomData); /// Contents `self.1` when `self.0` is true. pub struct When(bool, A, PhantomData); impl> Content for When { fn layout (&self, to: E::Area) -> E::Area { let Self(cond, item, ..) = self; let mut area = E::Area::zero(); if *cond { let item_area = item.layout(to); area[0] = item_area.x(); area[1] = item_area.y(); area[2] = item_area.w(); area[3] = item_area.h(); } area.into() } fn render (&self, to: &mut E::Output) { let Self(cond, item, ..) = self; if *cond { item.render(to) } } } /// Contents `self.1` when `self.0` is true, otherwise renders `self.2` pub struct Either(bool, A, B, PhantomData); impl, B: Content> Content for Either { fn layout (&self, to: E::Area) -> E::Area { let Self(cond, a, b, ..) = self; if *cond { a.layout(to) } else { b.layout(to) } } fn render (&self, to: &mut E::Output) { let Self(cond, a, b, ..) = self; if *cond { a.render(to) } else { b.render(to) } } } pub struct Map(PhantomData, J, F) where E: Engine, I: Iterator + Send + Sync, J: Fn()->I + Send + Sync, R: Content, F: Fn(T, usize)->R + Send + Sync; impl Content for Map where E: Engine, I: Iterator + Send + Sync, J: Fn()->I + Send + Sync, R: Content, F: Fn(T, usize)->R + Send + Sync { fn layout (&self, area: E::Area) -> E::Area { let mut index = 0; let [mut min_x, mut min_y] = area.center(); let [mut max_x, mut max_y] = area.center(); for item in (self.1)() { let area = (self.2)(item, index).layout(area).xywh(); let [x,y,w,h] = area.xywh(); min_x = min_x.min(x.into()); min_y = min_y.min(y.into()); max_x = max_x.max((x + w).into()); max_y = max_y.max((y + h).into()); index += 1; } let w = max_x - min_x; let h = max_y - min_y; //[min_x.into(), min_y.into(), w.into(), h.into()].into() area.center_xy([w.into(), h.into()].into()).into() } fn render (&self, to: &mut E::Output) { let mut index = 0; let area = self.layout(to.area()); //panic!("{area:?}"); //to.blit(&format!("{area:?}"), 0, 0, None); for item in (self.1)() { let item = (self.2)(item, index); to.place(area.into(), &item); index += 1; } } } /* pub struct Reduce(PhantomData<(E, R)>, I, F) where E: Engine, I: Iterator + Send + Sync, R: Content, F: Fn(R, T, usize) -> R + Send + Sync; impl Content for Reduce where E: Engine, I: Iterator + Send + Sync, R: Content, F: Fn(R, T, usize) -> R + Send + Sync { fn render (&self, to: &mut E::Output) { todo!() } } */