mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
semblance of groovebox launches from edn layout!
This commit is contained in:
parent
a702170d16
commit
7b3de1e68d
7 changed files with 209 additions and 152 deletions
|
|
@ -41,16 +41,29 @@ impl<E: Output, T: EdnViewData<E> + Send + Sync> Content<E> for EdnView<E, T> {
|
||||||
fn content (&self) -> impl Render<E> {
|
fn content (&self) -> impl Render<E> {
|
||||||
use EdnItem::*;
|
use EdnItem::*;
|
||||||
match self {
|
match self {
|
||||||
Self::Ok(state, layout) => match layout {
|
Self::Ok(s, layout) => match layout {
|
||||||
Nil => ().boxed(),
|
Nil => ().boxed(),
|
||||||
Sym(t) => state.get_content(Sym(t.as_str())).boxed(),
|
Sym(t) => s.get_content(Sym(t.as_str())).boxed(),
|
||||||
Key(t) => panic!("todo: add error handling to content() chain. unexpected key {t}"),
|
Key(t) => panic!("todo: add error handling to content() chain. unexpected key {t}"),
|
||||||
Num(n) => panic!("todo: add error handling to content() chain. unexpected num {n}"),
|
Num(n) => panic!("todo: add error handling to content() chain. unexpected num {n}"),
|
||||||
Exp(e) => if let [head, tail @ ..] = e.as_slice() {
|
Exp(e) => if let [head, tail @ ..] = e.as_slice() {
|
||||||
let head = &head.to_ref();
|
let head = &head.to_ref();
|
||||||
match (head, tail) {
|
match (head, tail) {
|
||||||
(Key("when"), [c, a]) => When(state.get_bool(c.to_ref()), state.get_content(a.to_ref())).boxed(),
|
(Key("align/e"), [a]) => Align::e(s.get_content(a.to_ref())).boxed(),
|
||||||
(Key("bsp/s"), [a, b]) => Bsp::s(state.get_content(a.to_ref()), state.get_content(b.to_ref()),).boxed(),
|
(Key("align/w"), [a]) => Align::w(s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("align/x"), [a]) => Align::x(s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("bsp/s"), [a, b]) => Bsp::s(s.get_content(a.to_ref()), s.get_content(b.to_ref()),).boxed(),
|
||||||
|
(Key("bsp/n"), [a, b]) => Bsp::n(s.get_content(a.to_ref()), s.get_content(b.to_ref()),).boxed(),
|
||||||
|
(Key("bsp/e"), [a, b]) => Bsp::e(s.get_content(a.to_ref()), s.get_content(b.to_ref()),).boxed(),
|
||||||
|
(Key("fill/x"), [a]) => Fill::x(s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("fill/xy"), [a]) => Fill::xy(s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("fixed/x"), [x, a]) => Fixed::x(s.get_unit(x.to_ref()), s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("fixed/y"), [y, a]) => Fixed::y(s.get_unit(y.to_ref()), s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("push/y"), [y, a]) => Push::y(s.get_unit(y.to_ref()), s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("max/y"), [y, a]) => Max::y(s.get_unit(y.to_ref()), s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("lay"), args) => Map(||args.iter(), |a, _|s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("row"), args) => Map(||args.iter(), |a, _|s.get_content(a.to_ref())).boxed(),
|
||||||
|
(Key("when"), [c, a]) => When(s.get_bool(c.to_ref()), s.get_content(a.to_ref())).boxed(),
|
||||||
_ => todo!("{:?} {:?}", &head, &tail)
|
_ => todo!("{:?} {:?}", &head, &tail)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
16
layout/src/either.rs
Normal file
16
layout/src/either.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// Show one item if a condition is true and another if the condition is false
|
||||||
|
pub struct Either<A, B>(pub bool, pub A, pub B);
|
||||||
|
|
||||||
|
impl<E: Output, A: Render<E>, B: Render<E>> Content<E> for Either<A, B> {
|
||||||
|
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) {
|
||||||
|
let Self(cond, a, b) = self;
|
||||||
|
if *cond { a.render(to) } else { b.render(to) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
|
||||||
|
mod when; pub use self::when::*;
|
||||||
|
mod either; pub use self::either::*;
|
||||||
|
mod map; pub use self::map::*;
|
||||||
|
mod reduce; pub use self::reduce::*;
|
||||||
|
|
||||||
mod align; pub use self::align::*;
|
mod align; pub use self::align::*;
|
||||||
mod direction; pub use self::direction::*;
|
mod direction; pub use self::direction::*;
|
||||||
mod measure; pub use self::measure::*;
|
mod measure; pub use self::measure::*;
|
||||||
mod ops; pub use self::ops::*;
|
|
||||||
mod transform_xy; pub use self::transform_xy::*;
|
mod transform_xy; pub use self::transform_xy::*;
|
||||||
mod transform_xy_unit; pub use self::transform_xy_unit::*;
|
mod transform_xy_unit; pub use self::transform_xy_unit::*;
|
||||||
|
|
||||||
|
|
|
||||||
55
layout/src/map.rs
Normal file
55
layout/src/map.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub fn map_south<O: Output>(
|
||||||
|
item_offset: O::Unit,
|
||||||
|
item_height: O::Unit,
|
||||||
|
item: impl Content<O>
|
||||||
|
) -> impl Content<O> {
|
||||||
|
Push::y(item_offset,
|
||||||
|
Align::n(Fixed::y(item_height,
|
||||||
|
Fill::x(item))))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Map<A, B, I, F, G>(pub F, pub G) where
|
||||||
|
I: Iterator<Item = A> + Send + Sync,
|
||||||
|
F: Fn() -> I + Send + Sync,
|
||||||
|
G: Fn(A, usize)->B + Send + Sync;
|
||||||
|
|
||||||
|
impl<E, A, B, I, F, G> Content<E> for Map<A, B, I, F, G> where
|
||||||
|
E: Output,
|
||||||
|
B: Render<E>,
|
||||||
|
I: Iterator<Item = A> + Send + Sync,
|
||||||
|
F: Fn() -> I + Send + Sync,
|
||||||
|
G: Fn(A, usize)->B + Send + Sync
|
||||||
|
{
|
||||||
|
fn layout (&self, area: E::Area) -> E::Area {
|
||||||
|
let Self(get_iterator, callback) = self;
|
||||||
|
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 get_iterator() {
|
||||||
|
let area = callback(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) {
|
||||||
|
let Self(get_iterator, callback) = self;
|
||||||
|
let mut index = 0;
|
||||||
|
//let area = self.layout(to.area());
|
||||||
|
for item in get_iterator() {
|
||||||
|
let item = callback(item, index);
|
||||||
|
//to.place(area.into(), &item);
|
||||||
|
to.place(to.area().into(), &item);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// Show an item only when a condition is true.
|
|
||||||
pub struct When<A>(pub bool, pub A);
|
|
||||||
|
|
||||||
impl<E: Output, A: Render<E>> Content<E> for When<A> {
|
|
||||||
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) {
|
|
||||||
let Self(cond, item) = self;
|
|
||||||
if *cond { item.render(to) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Show one item if a condition is true and another if the condition is false
|
|
||||||
pub struct Either<A, B>(pub bool, pub A, pub B);
|
|
||||||
|
|
||||||
impl<E: Output, A: Render<E>, B: Render<E>> Content<E> for Either<A, B> {
|
|
||||||
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) {
|
|
||||||
let Self(cond, a, b) = self;
|
|
||||||
if *cond { a.render(to) } else { b.render(to) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Map<A, B, I, F, G>(pub F, pub G) where
|
|
||||||
I: Iterator<Item = A> + Send + Sync,
|
|
||||||
F: Fn() -> I + Send + Sync,
|
|
||||||
G: Fn(A, usize)->B + Send + Sync;
|
|
||||||
|
|
||||||
impl<E, A, B, I, F, G> Content<E> for Map<A, B, I, F, G> where
|
|
||||||
E: Output,
|
|
||||||
B: Render<E>,
|
|
||||||
I: Iterator<Item = A> + Send + Sync,
|
|
||||||
F: Fn() -> I + Send + Sync,
|
|
||||||
G: Fn(A, usize)->B + Send + Sync
|
|
||||||
{
|
|
||||||
fn layout (&self, area: E::Area) -> E::Area {
|
|
||||||
let Self(get_iterator, callback) = self;
|
|
||||||
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 get_iterator() {
|
|
||||||
let area = callback(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) {
|
|
||||||
let Self(get_iterator, callback) = self;
|
|
||||||
let mut index = 0;
|
|
||||||
//let area = self.layout(to.area());
|
|
||||||
for item in get_iterator() {
|
|
||||||
let item = callback(item, index);
|
|
||||||
//to.place(area.into(), &item);
|
|
||||||
to.place(to.area().into(), &item);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
//pub fn reduce <E, T, I, R, F>(iterator: I, callback: F) -> Reduce<E, T, I, R, F> where
|
|
||||||
//E: Output,
|
|
||||||
//I: Iterator<Item = T> + Send + Sync,
|
|
||||||
//R: Render<E>,
|
|
||||||
//F: Fn(R, T, usize) -> R + Send + Sync
|
|
||||||
//{
|
|
||||||
//Reduce(Default::default(), iterator, callback)
|
|
||||||
//}
|
|
||||||
pub struct Reduce<E, T, I, R, F>(PhantomData<(E, R)>, I, F) where
|
|
||||||
E: Output,
|
|
||||||
I: Iterator<Item = T> + Send + Sync,
|
|
||||||
R: Render<E>,
|
|
||||||
F: Fn(R, T, usize) -> R + Send + Sync;
|
|
||||||
impl<E, T, I, R, F> Content<E> for Reduce<E, T, I, R, F> where
|
|
||||||
E: Output,
|
|
||||||
I: Iterator<Item = T> + Send + Sync,
|
|
||||||
R: Render<E>,
|
|
||||||
F: Fn(R, T, usize) -> R + Send + Sync
|
|
||||||
{
|
|
||||||
fn render (&self, to: &mut E) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//macro_rules! define_ops {
|
|
||||||
//($Trait:ident<$E:ident:$Output:path> { $(
|
|
||||||
//$(#[$attr:meta $($attr_args:tt)*])*
|
|
||||||
//(
|
|
||||||
//$fn:ident
|
|
||||||
//$(<$($G:ident$(:$Gen:path)?, )+>)?
|
|
||||||
//$Op:ident
|
|
||||||
//($($arg:ident:$Arg:ty),*)
|
|
||||||
//)
|
|
||||||
//)* }) => {
|
|
||||||
//impl<$E: $Output> $Trait<E> for E {}
|
|
||||||
//pub trait $Trait<$E: $Output> {
|
|
||||||
//$(
|
|
||||||
//$(#[$attr $($attr_args)*])*
|
|
||||||
//fn $fn $(<$($G),+>)?
|
|
||||||
//($($arg:$Arg),*)-> $Op<$($(, $G)+)?>
|
|
||||||
//$(where $($G: $($Gen + Send + Sync)?),+)?
|
|
||||||
//{ $Op($($arg),*) }
|
|
||||||
//)*
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//define_ops! {
|
|
||||||
//Layout<E: Output> {
|
|
||||||
//(when <A: Render<E>,>
|
|
||||||
//When(cond: bool, item: A))
|
|
||||||
///// When `cond` is `true`, render `a`, otherwise render `b`.
|
|
||||||
//(either <A: Render<E>, B: Render<E>,>
|
|
||||||
//Either(cond: bool, a: A, b: B))
|
|
||||||
///// If `opt` is `Some(T)` renders `cb(t)`, otherwise nothing.
|
|
||||||
//(opt <A, F: Fn(A) -> B, B: Render<E>,>
|
|
||||||
//Opt(option: Option<A>, cb: F))
|
|
||||||
///// Maps items of iterator through callback.
|
|
||||||
//(map <A, B: Render<E>, I: Iterator<Item = A>, F: Fn() -> I, G: Fn(A, usize)->B,>
|
|
||||||
//Map(get_iterator: F, callback: G))
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
93
layout/src/reduce.rs
Normal file
93
layout/src/reduce.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub struct Reduce<A, B, I, F, G>(pub PhantomData<A>, pub F, pub G) where
|
||||||
|
A: Send + Sync, B: Send + Sync,
|
||||||
|
I: Iterator<Item = B> + Send + Sync,
|
||||||
|
F: Fn() -> I + Send + Sync,
|
||||||
|
G: Fn(A, B, usize)->A + Send + Sync;
|
||||||
|
|
||||||
|
impl<A, B, I, F, G> Reduce<A, B, I, F, G> where
|
||||||
|
A: Send + Sync, B: Send + Sync,
|
||||||
|
I: Iterator<Item = B> + Send + Sync,
|
||||||
|
F: Fn() -> I + Send + Sync,
|
||||||
|
G: Fn(A, B, usize)->A + Send + Sync
|
||||||
|
{
|
||||||
|
pub fn new (f: F, g: G) -> Self { Self(Default::default(), f, g) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Output, A, B, I, F, G> Content<E> for Reduce<A, B, I, F, G> where
|
||||||
|
A: Send + Sync, B: Send + Sync,
|
||||||
|
I: Iterator<Item = B> + Send + Sync,
|
||||||
|
F: Fn() -> I + Send + Sync,
|
||||||
|
G: Fn(A, B, usize)->A + Send + Sync
|
||||||
|
{
|
||||||
|
fn content (&self) -> impl Render<E> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
//pub fn reduce <E, T, I, R, F>(iterator: I, callback: F) -> Reduce<E, T, I, R, F> where
|
||||||
|
//E: Output,
|
||||||
|
//I: Iterator<Item = T> + Send + Sync,
|
||||||
|
//R: Render<E>,
|
||||||
|
//F: Fn(R, T, usize) -> R + Send + Sync
|
||||||
|
//{
|
||||||
|
//Reduce(Default::default(), iterator, callback)
|
||||||
|
//}
|
||||||
|
pub struct Reduce<E, T, I, R, F>(PhantomData<(E, R)>, I, F) where
|
||||||
|
E: Output,
|
||||||
|
I: Iterator<Item = T> + Send + Sync,
|
||||||
|
R: Render<E>,
|
||||||
|
F: Fn(R, T, usize) -> R + Send + Sync;
|
||||||
|
impl<E, T, I, R, F> Content<E> for Reduce<E, T, I, R, F> where
|
||||||
|
E: Output,
|
||||||
|
I: Iterator<Item = T> + Send + Sync,
|
||||||
|
R: Render<E>,
|
||||||
|
F: Fn(R, T, usize) -> R + Send + Sync
|
||||||
|
{
|
||||||
|
fn render (&self, to: &mut E) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//macro_rules! define_ops {
|
||||||
|
//($Trait:ident<$E:ident:$Output:path> { $(
|
||||||
|
//$(#[$attr:meta $($attr_args:tt)*])*
|
||||||
|
//(
|
||||||
|
//$fn:ident
|
||||||
|
//$(<$($G:ident$(:$Gen:path)?, )+>)?
|
||||||
|
//$Op:ident
|
||||||
|
//($($arg:ident:$Arg:ty),*)
|
||||||
|
//)
|
||||||
|
//)* }) => {
|
||||||
|
//impl<$E: $Output> $Trait<E> for E {}
|
||||||
|
//pub trait $Trait<$E: $Output> {
|
||||||
|
//$(
|
||||||
|
//$(#[$attr $($attr_args)*])*
|
||||||
|
//fn $fn $(<$($G),+>)?
|
||||||
|
//($($arg:$Arg),*)-> $Op<$($(, $G)+)?>
|
||||||
|
//$(where $($G: $($Gen + Send + Sync)?),+)?
|
||||||
|
//{ $Op($($arg),*) }
|
||||||
|
//)*
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//define_ops! {
|
||||||
|
//Layout<E: Output> {
|
||||||
|
//(when <A: Render<E>,>
|
||||||
|
//When(cond: bool, item: A))
|
||||||
|
///// When `cond` is `true`, render `a`, otherwise render `b`.
|
||||||
|
//(either <A: Render<E>, B: Render<E>,>
|
||||||
|
//Either(cond: bool, a: A, b: B))
|
||||||
|
///// If `opt` is `Some(T)` renders `cb(t)`, otherwise nothing.
|
||||||
|
//(opt <A, F: Fn(A) -> B, B: Render<E>,>
|
||||||
|
//Opt(option: Option<A>, cb: F))
|
||||||
|
///// Maps items of iterator through callback.
|
||||||
|
//(map <A, B: Render<E>, I: Iterator<Item = A>, F: Fn() -> I, G: Fn(A, usize)->B,>
|
||||||
|
//Map(get_iterator: F, callback: G))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
23
layout/src/when.rs
Normal file
23
layout/src/when.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// Show an item only when a condition is true.
|
||||||
|
pub struct When<A>(pub bool, pub A);
|
||||||
|
|
||||||
|
impl<E: Output, A: Render<E>> Content<E> for When<A> {
|
||||||
|
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) {
|
||||||
|
let Self(cond, item) = self;
|
||||||
|
if *cond { item.render(to) }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue