From a0175dabc8b299be72a37698bf38f202784cedf7 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 30 Dec 2024 20:51:16 +0100 Subject: [PATCH] wip: big flat pt.10, down to 33 --- engine/src/tui.rs | 2 +- src/arranger/arranger_v/v_clips.rs | 2 +- src/groovebox.rs | 2 +- src/lib.rs | 2 +- src/midi/midi_editor.rs | 2 +- src/sampler/sampler_tui.rs | 2 +- src/space.rs | 448 ----------------------------- src/space/collect.rs | 80 ------ src/space/cond.rs | 23 -- src/space/coord.rs | 14 - src/space/layers.rs | 37 --- src/space/map_reduce.rs | 33 --- src/space/measure.rs | 65 ----- src/space/position.rs | 191 ------------ src/space/scroll.rs | 1 - src/space/size.rs | 217 -------------- src/space/split.rs | 247 ---------------- 17 files changed, 6 insertions(+), 1362 deletions(-) delete mode 100644 src/space.rs delete mode 100644 src/space/collect.rs delete mode 100644 src/space/cond.rs delete mode 100644 src/space/coord.rs delete mode 100644 src/space/layers.rs delete mode 100644 src/space/map_reduce.rs delete mode 100644 src/space/measure.rs delete mode 100644 src/space/position.rs delete mode 100644 src/space/scroll.rs delete mode 100644 src/space/size.rs delete mode 100644 src/space/split.rs diff --git a/engine/src/tui.rs b/engine/src/tui.rs index 33ebafa6..56abbe5d 100644 --- a/engine/src/tui.rs +++ b/engine/src/tui.rs @@ -331,7 +331,7 @@ pub fn half_block (lower: bool, upper: bool) -> Option { //impl> Render for T {} -impl Render for str { +impl Render for &str { fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { // TODO: line breaks Ok(Some([self.chars().count() as u16, 1])) diff --git a/src/arranger/arranger_v/v_clips.rs b/src/arranger/arranger_v/v_clips.rs index 18319862..b0805ffe 100644 --- a/src/arranger/arranger_v/v_clips.rs +++ b/src/arranger/arranger_v/v_clips.rs @@ -31,7 +31,7 @@ impl<'a> ArrangerVClips<'a> { Tui::bg(scene.color.base.rgb, if playing { "▶ " } else { " " }), Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb, - Grow::x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))), + Expand::x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))), row!((index, track, x1, x2) in ArrangerTrack::with_widths(tracks) => { Self::format_clip(scene, index, track, (x2 - x1) as u16, height) })]) diff --git a/src/groovebox.rs b/src/groovebox.rs index 829a593c..cdf5a99a 100644 --- a/src/groovebox.rs +++ b/src/groovebox.rs @@ -143,7 +143,7 @@ render!(|self:Groovebox|{ struct EditStatus<'a, T: Render>(&'a Sampler, &'a MidiEditor, usize, T); impl<'a, T: Render> Content for EditStatus<'a, T> { - fn content (&self) -> impl Render { + fn content (&self) -> Option> { Some(Split::n(false, 9, col!([ row!(|add|{ if let Some(sample) = &self.0.mapped[self.2] { diff --git a/src/lib.rs b/src/lib.rs index 060b0df6..3f60a456 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ pub mod pool; pub use self::pool::*; pub mod sampler; pub use self::sampler::*; pub mod sequencer; pub use self::sequencer::*; pub mod status; pub use self::status::*; -pub mod style; pub use self::theme::*; +pub mod style; pub use self::style::*; pub mod theme; pub use self::theme::*; pub mod time; pub use self::time::*; pub mod transport; pub use self::transport::*; diff --git a/src/midi/midi_editor.rs b/src/midi/midi_editor.rs index 6bfc59a8..2f23a620 100644 --- a/src/midi/midi_editor.rs +++ b/src/midi/midi_editor.rs @@ -131,7 +131,7 @@ pub trait PhraseViewMode: Render + HasSize + MidiRange + MidiPoint + D } impl Content for Box { - fn content (&self) -> impl Render { + fn content (&self) -> Option> { Some(&(*self)) } } diff --git a/src/sampler/sampler_tui.rs b/src/sampler/sampler_tui.rs index da333d9a..dcde284d 100644 --- a/src/sampler/sampler_tui.rs +++ b/src/sampler/sampler_tui.rs @@ -53,7 +53,7 @@ render!(|self: SamplerTui|{ let with_border = |x|lay!([border, Fill::xy(&x)]); let with_size = |x|lay!([self.size, x]); Tui::bg(bg, Fill::xy(with_border(Bsp::s( - Tui::fg(self.color.light.rgb, Tui::bold(true, "Sampler")), + Tui::fg(self.color.light.rgb, Tui::bold(true, &"Sampler")), with_size(Shrink::y(1, Bsp::e( Fixed::x(keys_width, keys()), Fill::xy(render(|to: &mut TuiOutput|Ok({ diff --git a/src/space.rs b/src/space.rs deleted file mode 100644 index 9e514ae4..00000000 --- a/src/space.rs +++ /dev/null @@ -1,448 +0,0 @@ -use crate::*; -use std::ops::{Add, Sub, Mul, Div}; -use std::fmt::{Display, Debug}; - -mod cond; pub use self::cond::*; -mod coord; pub use self::coord::*; -mod layers; pub use self::layers::*; -mod measure; pub use self::measure::*; -mod position; pub use self::position::*; -mod scroll; pub use self::scroll::*; -mod size; pub use self::size::*; -mod split; pub use self::split::*; - -/// A cardinal direction. -#[derive(Copy, Clone, PartialEq)] -pub enum Direction { North, South, West, East, } -pub use self::Direction::{self, *}; - -impl Direction { - #[inline] fn split_fixed (self, area: Area, a: N) -> ([N;4],[N;4]) { - match area { - Direction::North => ( - [area.x(), (area.y()+area.h()).minus(a), area.w(), a], - [area.x(), area.y(), area.w(), area.h().minus(a)], - ), - Direction::South => ( - [area.x(), area.y(), area.w(), a], - [area.x(), area.y() + a, area.w(), area.h().minus(a)], - ), - Direction::East => ( - [area.x(), area.y(), a, area.h()], - [area.x() + a, area.y(), area.w().minus(a), area.h()], - ), - Direction::West => ( - [area.x() + area.w() - a, area.y(), a, area.h()], - [area.x(), area.y(), area.w() - a, area.h()], - ), - } - } -} - -trait AreaMod: Area { - fn x2 (&self) -> N { - self.x() + self.w() - } - fn y2 (&self) -> N { - self.y() + self.h() - } - #[inline] fn wh (&self) -> [N;2] { - [self.w(), self.h()] - } - #[inline] fn xywh (&self) -> [N;4] { - [self.x(), self.y(), self.w(), self.h()] - } - #[inline] fn lrtb (&self) -> [N;4] { - [self.x(), self.x2(), self.y(), self.y2()] - } - #[inline] fn push_x (&self, x: N) -> [N;4] { - [self.x() + x, self.y(), self.w(), self.h()] - } - #[inline] fn push_y (&self, y: N) -> [N;4] { - [self.x(), self.y() + y, self.w(), self.h()] - } - #[inline] fn shrink_x (&self, x: N) -> [N;4] { - [self.x(), self.y(), self.w().minus(x), self.h()] - } - #[inline] fn shrink_y (&self, y: N) -> [N;4] { - [self.x(), self.y(), self.w(), self.h().minus(y)] - } - #[inline] fn set_w (&self, w: N) -> [N;4] { - [self.x(), self.y(), w, self.h()] - } - #[inline] fn set_h (&self, h: N) -> [N;4] { - [self.x(), self.y(), self.w(), h] - } - #[inline] fn clip_h (&self, h: N) -> [N;4] { - [self.x(), self.y(), self.w(), self.h().min(h)] - } - #[inline] fn clip_w (&self, w: N) -> [N;4] { - [self.x(), self.y(), self.w().min(w), self.h()] - } - #[inline] fn clip (&self, wh: impl Size) -> [N;4] { - [self.x(), self.y(), wh.w(), wh.h()] - } -} - -/// Renders multiple things on top of each other, -/// in the order they are provided by the callback. -/// Total size is largest width x largest height. -pub struct Layers< - E: Engine, - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> ->(pub F, PhantomData); - -/// Shorthand for defining an instance of [Layers]. -#[macro_export] macro_rules! lay { - ([$($expr:expr),* $(,)?]) => { - Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Layers::new(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Layers::new($expr) - }; -} - - -pub trait HasSize { - fn size (&self) -> &Measure; -} - -#[macro_export] macro_rules! has_size { - (<$E:ty>|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { - impl $(<$($L),*$($T $(: $U)?),*>)? HasSize<$E> for $Struct $(<$($L),*$($T),*>)? { - fn size (&$self) -> &Measure<$E> { $cb } - } - } -} - -/// A widget that tracks its render width and height -#[derive(Default)] -pub struct Measure { - _engine: PhantomData, - pub x: Arc, - pub y: Arc, -} - -pub struct ShowMeasure<'a>(&'a Measure); - -pub trait LayoutDebug { - fn debug > (other: W) -> DebugOverlay { - DebugOverlay(Default::default(), other) - } -} - -pub struct DebugOverlay>(PhantomData, pub W); - -impl> Render for DebugOverlay { - fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> { - self.1.min_size(to) - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - let [x, y, w, h] = to.area(); - self.1.render(to)?; - Ok(to.blit(&format!("{w}x{h}+{x}+{y}"), x, y, Some(Style::default().green()))) - } -} - - -macro_rules! by_axis { - (!$Enum:ident) => { - impl> $Enum { - pub fn x (item: T) -> Self { - Self::X(item) - } - pub fn y (item: T) -> Self { - Self::Y(item) - } - pub fn xy (item: T) -> Self { - Self::XY(item) - } - } - }; - (+$Enum:ident) => { - impl> $Enum { - pub fn x (x: E::Unit, item: T) -> Self { - Self::X(x, item) - } - pub fn y (y: E::Unit, item: T) -> Self { - Self::Y(y, item) - } - pub fn xy (x: E::Unit, y: E::Unit, item: T) -> Self { - Self::XY(x, y, item) - } - } - }; -} - -/// Shrink drawing area -pub enum Shrink> { - /// Decrease width - X(E::Unit, T), - /// Decrease height - Y(E::Unit, T), - /// Decrease width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Shrink); - -/// Expand drawing area -pub enum Grow> { - /// Increase width - X(E::Unit, T), - /// Increase height - Y(E::Unit, T), - /// Increase width and height - XY(E::Unit, E::Unit, T) -} - -by_axis!(+Grow); - -pub enum Fill> { - _Unused(PhantomData), - /// Maximize width - X(W), - /// Maximize height - Y(W), - /// Maximize width and height - XY(W), -} - -by_axis!(!Fill); - -/// Enforce fixed size of drawing area -pub enum Fixed> { - /// Set width - X(E::Unit, T), - /// Set height - Y(E::Unit, T), - /// Set width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Fixed); - -/// Enforce minimum size of drawing area -pub enum Min> { - /// Enforce minimum width - X(E::Unit, T), - /// Enforce minimum height - Y(E::Unit, T), - /// Enforce minimum width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Min); - -/// Enforce maximum size of drawing area -pub enum Max> { - /// Enforce maximum width - X(E::Unit, T), - /// Enforce maximum height - Y(E::Unit, T), - /// Enforce maximum width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Max); - -/// Increment origin point of drawing area -pub enum Push> { - /// Move origin to the right - X(E::Unit, T), - /// Move origin downwards - Y(E::Unit, T), - /// Move origin to the right and downwards - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Push); - -/// Decrement origin point of drawing area -pub enum Pull> { - /// Move origin to the right - X(E::Unit, T), - /// Move origin downwards - Y(E::Unit, T), - /// Move origin to the right and downwards - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Pull); - -/// Shrink from each side -pub enum Padding { - /// Decrease width - X(E::Unit, T), - /// Decrease height - Y(E::Unit, T), - /// Decrease width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Padding); - -/// Grow on each side -pub enum Margin> { - /// Increase width - X(E::Unit, T), - /// Increase height - Y(E::Unit, T), - /// Increase width and height - XY(E::Unit, E::Unit, T), -} - -by_axis!(+Margin); - -/// A binary split with fixed proportion -pub struct Split(pub bool, pub Direction, pub E::Unit, A, B, PhantomData) -where E: Engine, A: Render, B: Render; - -impl, B: Render> Split { - #[inline] pub fn new (flip: bool, direction: Direction, proportion: E::Unit, a: A, b: B) -> Self { - Self(flip, direction, proportion, a, b, Default::default()) - } - #[inline] pub fn n (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { - Self::new(flip, North, proportion, a, b) - } - #[inline] pub fn s (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { - Self::new(flip, South, proportion, a, b) - } - #[inline] pub fn e (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { - Self::new(flip, West, proportion, a, b) - } - #[inline] pub fn w (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { - Self::new(flip, East, proportion, a, b) - } -} - -pub enum Bsp, Y: Render> { - /// X is north of Y - N(Option, Option), - /// X is south of Y - S(Option, Option), - /// X is east of Y - E(Option, Option), - /// X is west of Y - W(Option, Option), - /// X is above Y - A(Option, Option), - /// X is below Y - B(Option, Option), - /// Should be avoided. - Null(PhantomData), -} - -impl, Y: Render> Bsp { - pub fn new (x: X) -> Self { Self::A(Some(x), None) } - pub fn n (x: X, y: Y) -> Self { Self::N(Some(x), Some(y)) } - pub fn s (x: X, y: Y) -> Self { Self::S(Some(x), Some(y)) } - pub fn e (x: X, y: Y) -> Self { Self::E(Some(x), Some(y)) } - pub fn w (x: X, y: Y) -> Self { Self::W(Some(x), Some(y)) } - pub fn a (x: X, y: Y) -> Self { Self::A(Some(x), Some(y)) } - pub fn b (x: X, y: Y) -> Self { Self::B(Some(x), Some(y)) } -} - -pub struct Stack< - E: Engine, - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> ->(pub F, pub Direction, PhantomData); - -impl< - E: Engine, - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> -> Stack { - #[inline] pub fn new (direction: Direction, build: F) -> Self { - Self(build, direction, Default::default()) - } - #[inline] pub fn right (build: F) -> Self { - Self::new(East, build) - } - #[inline] pub fn down (build: F) -> Self { - Self::new(South, build) - } - #[inline] pub fn up (build: F) -> Self { - Self::new(North, build) - } -} - -#[macro_export] macro_rules! col { - ([$($expr:expr),* $(,)?]) => { - Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::down(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::down($expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::down(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - -#[macro_export] macro_rules! col_up { - ([$($expr:expr),* $(,)?]) => { - Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::up(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::up(expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::up(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - -#[macro_export] macro_rules! row { - ([$($expr:expr),* $(,)?]) => { - Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::right(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::right($expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::right(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - -/// A scrollable area. -pub struct Scroll(pub F, pub Direction, pub u64, PhantomData) -where - E: Engine, - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()>; - -/// Override X and Y coordinates, aligning to corner, side, or center of area -pub enum Align> { - _Unused(PhantomData), - /// Draw at center of container - Center(T), - /// Draw at center of X axis - X(T), - /// Draw at center of Y axis - Y(T), - /// Draw at upper left corner of contaier - NW(T), - /// Draw at center of upper edge of container - N(T), - /// Draw at right left corner of contaier - NE(T), - /// Draw at center of left edge of container - W(T), - /// Draw at center of right edge of container - E(T), - /// Draw at lower left corner of container - SW(T), - /// Draw at center of lower edge of container - S(T), - /// Draw at lower right edge of container - SE(T) -} diff --git a/src/space/collect.rs b/src/space/collect.rs deleted file mode 100644 index 99167436..00000000 --- a/src/space/collect.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::*; -use super::*; - -pub enum Collect<'a, E: Engine, const N: usize> { - Callback(CallbackCollection<'a, E>), - //Iterator(IteratorCollection<'a, E>), - Array(ArrayCollection<'a, E, N>), - Slice(SliceCollection<'a, E>), -} - -impl<'a, E: Engine, const N: usize> Collect<'a, E, N> { - pub fn iter (&'a self) -> CollectIterator<'a, E, N> { - CollectIterator(0, &self) - } -} - -impl<'a, E: Engine, const N: usize> From> for Collect<'a, E, N> { - fn from (callback: CallbackCollection<'a, E>) -> Self { - Self::Callback(callback) - } -} - -impl<'a, E: Engine, const N: usize> From> for Collect<'a, E, N> { - fn from (slice: SliceCollection<'a, E>) -> Self { - Self::Slice(slice) - } -} - -impl<'a, E: Engine, const N: usize> From> for Collect<'a, E, N>{ - fn from (array: ArrayCollection<'a, E, N>) -> Self { - Self::Array(array) - } -} - -type CallbackCollection<'a, E> = - &'a dyn Fn(&'a mut dyn FnMut(&dyn Render)->Usually<()>); - -//type IteratorCollection<'a, E> = - //&'a mut dyn Iterator>; - -type SliceCollection<'a, E> = - &'a [&'a dyn Render]; - -type ArrayCollection<'a, E, const N: usize> = - [&'a dyn Render; N]; - -pub struct CollectIterator<'a, E: Engine, const N: usize>(usize, &'a Collect<'a, E, N>); - -impl<'a, E: Engine, const N: usize> Iterator for CollectIterator<'a, E, N> { - type Item = &'a dyn Render; - fn next (&mut self) -> Option { - match self.1 { - Collect::Callback(callback) => { - todo!() - }, - //Collection::Iterator(iterator) => { - //iterator.next() - //}, - Collect::Array(array) => { - if let Some(item) = array.get(self.0) { - self.0 += 1; - //Some(item) - None - } else { - None - } - } - Collect::Slice(slice) => { - if let Some(item) = slice.get(self.0) { - self.0 += 1; - //Some(item) - None - } else { - None - } - } - } - } -} - diff --git a/src/space/cond.rs b/src/space/cond.rs deleted file mode 100644 index a3682f1a..00000000 --- a/src/space/cond.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::*; - -impl> Render for When { - fn min_size (&self, to: E::Size) -> Perhaps { - let Self(cond, item, ..) = self; - if *cond { item.min_size(to) } else { Ok(Some([0.into(), 0.into()].into())) } - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let Self(cond, item, ..) = self; - if *cond { item.render(to) } else { Ok(()) } - } -} - -impl, B: Render> Render for Either { - fn min_size (&self, to: E::Size) -> Perhaps { - let Self(cond, item, other, ..) = self; - if *cond { item.min_size(to) } else { other.min_size(to) } - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let Self(cond, item, other, ..) = self; - if *cond { item.render(to) } else { other.render(to) } - } -} diff --git a/src/space/coord.rs b/src/space/coord.rs deleted file mode 100644 index 59a29742..00000000 --- a/src/space/coord.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::*; -use super::*; - -impl Coordinate for T where T: Send + Sync + Copy - + Add - + Sub - + Mul - + Div - + Ord + PartialEq + Eq - + Debug + Display + Default - + From + Into - + Into - + Into -{} diff --git a/src/space/layers.rs b/src/space/layers.rs deleted file mode 100644 index b0736f24..00000000 --- a/src/space/layers.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::*; -use super::*; - -impl< - E: Engine, - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> -> Layers { - #[inline] - pub fn new (build: F) -> Self { - Self(build, Default::default()) - } -} - -impl Render for Layers -where - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> -{ - fn min_size (&self, area: E::Size) -> Perhaps { - let mut w: E::Unit = 0.into(); - let mut h: E::Unit = 0.into(); - (self.0)(&mut |layer| { - if let Some(layer_area) = layer.min_size(area)? { - w = w.max(layer_area.w()); - h = h.max(layer_area.h()); - } - Ok(()) - })?; - Ok(Some([w, h].into())) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - if let Some(size) = self.min_size(to.area().wh().into())? { - (self.0)(&mut |layer|to.render_in(to.area().clip(size).into(), layer)) - } else { - Ok(()) - } - } -} diff --git a/src/space/map_reduce.rs b/src/space/map_reduce.rs deleted file mode 100644 index 833973b2..00000000 --- a/src/space/map_reduce.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::*; - -impl+Send+Sync, T, R: Render> LayoutMapReduce for E {} - -pub trait LayoutMapReduce+Send+Sync, T, R: Render> { - fn map R> (iterator: I, callback: F) -> Map { - Map(Default::default(), iterator, callback) - } - fn reduce , T)->R+Send+Sync> (iterator: I, callback: F) -> Reduce { - Reduce(Default::default(), iterator, callback) - } -} - -pub struct Map, R: Render, F: Fn(T)->R>( - PhantomData, - I, - F -); - -pub struct Reduce, R: Render, F: Fn(&dyn Render, T)->R>( - PhantomData<(E, R)>, - I, - F -); - -impl+Send+Sync, R: Render, F: Fn(&dyn Render, T)->R+Send+Sync> Render for Reduce { - fn min_size (&self, to: E::Size) -> Perhaps { - todo!() - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - todo!() - } -} diff --git a/src/space/measure.rs b/src/space/measure.rs deleted file mode 100644 index 73ef5624..00000000 --- a/src/space/measure.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::*; -use super::*; - -impl LayoutDebug for E {} - -impl Clone for Measure { - fn clone (&self) -> Self { - Self { - _engine: Default::default(), - x: self.x.clone(), - y: self.y.clone(), - } - } -} - -impl std::fmt::Debug for Measure { - fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - f.debug_struct("Measure") - .field("width", &self.x) - .field("height", &self.y) - .finish() - } -} - -impl Measure { - pub fn w (&self) -> usize { self.x.load(Relaxed) } - pub fn h (&self) -> usize { self.y.load(Relaxed) } - pub fn wh (&self) -> [usize;2] { [self.w(), self.h()] } - pub fn set_w (&self, w: impl Into) { self.x.store(w.into(), Relaxed) } - pub fn set_h (&self, h: impl Into) { self.y.store(h.into(), Relaxed) } - pub fn set_wh (&self, w: impl Into, h: impl Into) { self.set_w(w); self.set_h(h); } - pub fn format (&self) -> String { format!("{}x{}", self.w(), self.h()) } - pub fn new () -> Self { - Self { - _engine: PhantomData::default(), - x: Arc::new(0.into()), - y: Arc::new(0.into()), - } - } -} - -impl Render for Measure { - fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { - Ok(Some([0u16.into(), 0u16.into()].into())) - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - self.set_w(to.area().w()); - self.set_h(to.area().h()); - Ok(()) - } -} - -impl Measure { - pub fn debug (&self) -> ShowMeasure { - ShowMeasure(&self) - } -} - -render!(|self: ShowMeasure<'a>|render(|to: &mut TuiOutput|Ok({ - let w = self.0.w(); - let h = self.0.h(); - to.blit(&format!(" {w} x {h} "), to.area.x(), to.area.y(), Some( - Style::default().bold().italic().bg(Color::Rgb(255, 0, 255)).fg(Color::Rgb(0,0,0)) - )) -}))); diff --git a/src/space/position.rs b/src/space/position.rs deleted file mode 100644 index 2039dfc0..00000000 --- a/src/space/position.rs +++ /dev/null @@ -1,191 +0,0 @@ -use crate::*; -use super::*; - -impl> Push { - pub fn inner (&self) -> &T { - use Push::*; - match self { X(_, i) => i, Y(_, i) => i, XY(_, _, i) => i, } - } - pub fn dx (&self) -> E::Unit { - use Push::*; - match self { X(x, _) => *x, Y(_, _) => E::Unit::default(), XY(x, _, _) => *x, } - } - pub fn dy (&self) -> E::Unit { - use Push::*; - match self { X(_, _) => E::Unit::default(), Y(y, _) => *y, XY(_, y, _) => *y, } - } -} - -impl> Render for Push { - fn min_size (&self, to: E::Size) -> Perhaps { - self.inner().min_size(to) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let area = to.area(); - Ok(self.min_size(area.wh().into())? - .map(|size|to.render_in(match *self { - Self::X(x, _) => [area.x() + x, area.y(), size.w(), size.h()], - Self::Y(y, _) => [area.x(), area.y() + y, size.w(), size.h()], - Self::XY(x, y, _) => [area.x() + x, area.y() + y, size.w(), size.h()], - }.into(), self.inner())).transpose()?.unwrap_or(())) - } -} - -impl> Pull { - pub fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - _ => unreachable!(), - } - } - pub fn dx (&self) -> E::Unit { - match self { - Self::X(x, _) => *x, - Self::Y(_, _) => E::Unit::default(), - Self::XY(x, _, _) => *x, - _ => unreachable!(), - } - } - pub fn dy (&self) -> E::Unit { - match self { - Self::X(_, _) => E::Unit::default(), - Self::Y(y, _) => *y, - Self::XY(_, y, _) => *y, - _ => unreachable!(), - } - } -} - -impl> Render for Pull { - fn min_size (&self, to: E::Size) -> Perhaps { - self.inner().min_size(to) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let area = to.area(); - Ok(self.min_size(area.wh().into())? - .map(|size|to.render_in(match *self { - Self::X(x, _) => [area.x().minus(x), area.y(), size.w(), size.h()], - Self::Y(y, _) => [area.x(), area.y().minus(y), size.w(), size.h()], - Self::XY(x, y, _) => [area.x().minus(x), area.y().minus(y), size.w(), size.h()], - _ => unreachable!(), - }.into(), self.inner())).transpose()?.unwrap_or(())) - } -} - -impl> Padding { - pub fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Render for Padding { - fn render (&self, to: &mut E::Output) -> Usually<()> { - match self { - Self::X(x, inner) => Push::x(*x, Shrink::x(*x, inner)), - Self::Y(y, inner) => Push::y(*y, Shrink::y(*y, inner)), - Self::XY(x, y, inner) => Push::xy(*x, *y, Shrink::xy(*x, *y, inner)), - }.render(to) - } -} - - -impl> Margin { - pub fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Render for Margin { - fn min_size (&self, to: E::Size) -> Perhaps { - match *self { - Self::X(x, ref inner) => Grow::x(x + x, inner), - Self::Y(y, ref inner) => Grow::y(y + y, inner), - Self::XY(x, y, ref inner) => Grow::xy(x + x, y + y, inner), - }.min_size(to) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - match *self { - Self::X(x, ref inner) => Push::x(x, inner), - Self::Y(y, ref inner) => Push::y(y, inner), - Self::XY(x, y, ref inner) => Push::xy(x, y, inner), - }.render(to) - } -} - -impl> Align { - pub fn c (w: T) -> Self { Self::Center(w) } - pub fn x (w: T) -> Self { Self::X(w) } - pub fn y (w: T) -> Self { Self::Y(w) } - pub fn n (w: T) -> Self { Self::N(w) } - pub fn s (w: T) -> Self { Self::S(w) } - pub fn e (w: T) -> Self { Self::E(w) } - pub fn w (w: T) -> Self { Self::W(w) } - pub fn nw (w: T) -> Self { Self::NW(w) } - pub fn sw (w: T) -> Self { Self::SW(w) } - pub fn ne (w: T) -> Self { Self::NE(w) } - pub fn se (w: T) -> Self { Self::SE(w) } - pub fn inner (&self) -> &T { - match self { - Self::Center(inner) => inner, - Self::X(inner) => inner, - Self::Y(inner) => inner, - Self::NW(inner) => inner, - Self::N(inner) => inner, - Self::NE(inner) => inner, - Self::W(inner) => inner, - Self::E(inner) => inner, - Self::SW(inner) => inner, - Self::S(inner) => inner, - Self::SE(inner) => inner, - _ => unreachable!(), - } - } -} - -fn align, N: Coordinate, R: Area + From<[N;4]>> (align: &Align, outer: R, inner: R) -> Option { - if outer.w() < inner.w() || outer.h() < inner.h() { - None - } else { - let [ox, oy, ow, oh] = outer.xywh(); - let [ix, iy, iw, ih] = inner.xywh(); - Some(match align { - Align::Center(_) => [ox + (ow - iw) / 2.into(), oy + (oh - ih) / 2.into(), iw, ih,].into(), - Align::X(_) => [ox + (ow - iw) / 2.into(), iy, iw, ih,].into(), - Align::Y(_) => [ix, oy + (oh - ih) / 2.into(), iw, ih,].into(), - Align::NW(_) => [ox, oy, iw, ih,].into(), - Align::N(_) => [ox + (ow - iw) / 2.into(), oy, iw, ih,].into(), - Align::NE(_) => [ox + ow - iw, oy, iw, ih,].into(), - Align::W(_) => [ox, oy + (oh - ih) / 2.into(), iw, ih,].into(), - Align::E(_) => [ox + ow - iw, oy + (oh - ih) / 2.into(), iw, ih,].into(), - Align::SW(_) => [ox, oy + oh - ih, iw, ih,].into(), - Align::S(_) => [ox + (ow - iw) / 2.into(), oy + oh - ih, iw, ih,].into(), - Align::SE(_) => [ox + ow - iw, oy + oh - ih, iw, ih,].into(), - _ => unreachable!() - }) - } -} - -impl> Render for Align { - fn min_size (&self, outer_area: E::Size) -> Perhaps { - self.inner().min_size(outer_area) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let outer_area = to.area(); - Ok(if let Some(inner_size) = self.min_size(outer_area.wh().into())? { - let inner_area = outer_area.clip(inner_size); - if let Some(aligned) = align(&self, outer_area.into(), inner_area.into()) { - to.render_in(aligned, self.inner())? - } - }) - } -} diff --git a/src/space/scroll.rs b/src/space/scroll.rs deleted file mode 100644 index c7b7e813..00000000 --- a/src/space/scroll.rs +++ /dev/null @@ -1 +0,0 @@ -use crate::*; diff --git a/src/space/size.rs b/src/space/size.rs deleted file mode 100644 index bcfcbdf8..00000000 --- a/src/space/size.rs +++ /dev/null @@ -1,217 +0,0 @@ -use crate::*; -use super::*; - -impl Size for (N, N) { - fn x (&self) -> N { self.0 } - fn y (&self) -> N { self.1 } -} - -impl Size for [N;2] { - fn x (&self) -> N { self[0] } - fn y (&self) -> N { self[1] } -} - -impl Area for (N, N, N, N) { - #[inline] fn x (&self) -> N { self.0 } - #[inline] fn y (&self) -> N { self.1 } - #[inline] fn w (&self) -> N { self.2 } - #[inline] fn h (&self) -> N { self.3 } -} - -impl Area for [N;4] { - #[inline] fn x (&self) -> N { self[0] } - #[inline] fn y (&self) -> N { self[1] } - #[inline] fn w (&self) -> N { self[2] } - #[inline] fn h (&self) -> N { self[3] } -} - -impl> Shrink { - fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Grow { - fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Render for Shrink { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(self.inner().min_size(to)?.map(|to|match *self { - Self::X(w, _) => [ - if to.w() > w { to.w() - w } else { 0.into() }, - to.h() - ], - Self::Y(h, _) => [ - to.w(), - if to.h() > h { to.h() - h } else { 0.into() } - ], - Self::XY(w, h, _) => [ - if to.w() > w { to.w() - w } else { 0.into() }, - if to.h() > h { to.h() - h } else { 0.into() } - ], - }.into())) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - Ok(self.min_size(to.area().wh().into())? - .map(|size|to.render_in(to.area().clip(size).into(), self.inner())) - .transpose()?.unwrap_or(())) - } -} - -impl> Render for Grow { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(self.inner().min_size(to)?.map(|to|match *self { - Self::X(w, _) => [to.w() + w, to.h()], - Self::Y(h, _) => [to.w(), to.h() + h], - Self::XY(w, h, _) => [to.w() + w, to.h() + h], - }.into())) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - Ok(self.min_size(to.area().wh().into())? - .map(|size|to.render_in(to.area().clip(size).into(), self.inner())) - .transpose()?.unwrap_or(())) - } -} - -impl> Fill { - fn inner (&self) -> &W { - match self { - Self::X(inner) => &inner, - Self::Y(inner) => &inner, - Self::XY(inner) => &inner, - _ => unreachable!(), - } - } - pub fn w (fill: W) -> Self { - Self::X(fill) - } - pub fn h (fill: W) -> Self { - Self::Y(fill) - } - pub fn wh (fill: W) -> Self { - Self::XY(fill) - } -} - -impl> Render for Fill { - fn min_size (&self, to: E::Size) -> Perhaps { - let area = self.inner().min_size(to.into())?; - if let Some(area) = area { - Ok(Some(match self { - Self::X(_) => [to.w().into(), area.h()], - Self::Y(_) => [area.w(), to.h().into()], - Self::XY(_) => [to.w().into(), to.h().into()], - _ => unreachable!(), - }.into())) - } else { - Ok(None) - } - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - self.inner().render(to) - } -} - -impl> Fixed { - pub fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - _ => unreachable!(), - } - } - pub fn w (x: E::Unit, w: T) -> Self { - Self::X(x, w) - } - pub fn h (y: E::Unit, w: T) -> Self { - Self::Y(y, w) - } - pub fn wh (x: E::Unit, y: E::Unit, w: T) -> Self { - Self::XY(x, y, w) - } -} - -impl> Render for Fixed { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(match self { - Self::X(w, _) => - if to.w() >= *w { Some([*w, to.h()].into()) } else { None }, - Self::Y(h, _) => - if to.h() >= *h { Some([to.w(), *h].into()) } else { None }, - Self::XY(w, h, _) - => if to.w() >= *w && to.h() >= *h { Some([*w, *h].into()) } else { None }, - _ => unreachable!(), - }) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - // 🡘 🡙 ←🡙→ - if let Some(size) = self.min_size(to.area().wh().into())? { - to.render_in(to.area().clip(size).into(), self.inner()) - } else { - Ok(()) - } - } -} - -impl> Min { - pub fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Render for Min { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(self.inner().min_size(to)?.map(|to|match *self { - Self::X(w, _) => [to.w().max(w), to.h()], - Self::Y(h, _) => [to.w(), to.h().max(h)], - Self::XY(w, h, _) => [to.w().max(w), to.h().max(h)], - }.into())) - } - // TODO: 🡘 🡙 ←🡙→ - fn render (&self, to: &mut E::Output) -> Usually<()> { - Ok(self.min_size(to.area().wh().into())? - .map(|size|to.render_in(to.area().clip(size).into(), self.inner())) - .transpose()?.unwrap_or(())) - } -} - -impl> Max { - fn inner (&self) -> &T { - match self { - Self::X(_, i) => i, - Self::Y(_, i) => i, - Self::XY(_, _, i) => i, - } - } -} - -impl> Render for Max { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(self.inner().min_size(to)?.map(|to|match *self { - Self::X(w, _) => [to.w().min(w), to.h()], - Self::Y(h, _) => [to.w(), to.h().min(h)], - Self::XY(w, h, _) => [to.w().min(w), to.h().min(h)], - }.into())) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - Ok(self.min_size(to.area().wh().into())? - .map(|size|to.render_in(to.area().clip(size).into(), self.inner())) - .transpose()?.unwrap_or(())) - } -} diff --git a/src/space/split.rs b/src/space/split.rs deleted file mode 100644 index 6bc8ef2d..00000000 --- a/src/space/split.rs +++ /dev/null @@ -1,247 +0,0 @@ -use crate::*; -use super::*; -use Direction::*; - -impl Direction { - pub fn is_north (&self) -> bool { matches!(self, Self::North) } - pub fn is_south (&self) -> bool { matches!(self, Self::South) } - pub fn is_east (&self) -> bool { matches!(self, Self::West) } - pub fn is_west (&self) -> bool { matches!(self, Self::East) } - /// Return next direction clockwise - pub fn cw (&self) -> Self { - match self { - Self::North => Self::East, - Self::South => Self::West, - Self::West => Self::North, - Self::East => Self::South, - } - } - /// Return next direction counterclockwise - pub fn ccw (&self) -> Self { - match self { - Self::North => Self::West, - Self::South => Self::East, - Self::West => Self::South, - Self::East => Self::North, - } - } -} - -impl, B: Render> Render for Split { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(Some(to)) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let (a, b) = to.area().split_fixed(self.1, self.2); - Ok(if self.0 { - to.render_in(a.into(), &self.4)?; - to.render_in(b.into(), &self.3)?; - } else { - to.render_in(a.into(), &self.3)?; - to.render_in(b.into(), &self.4)?; - }) - } -} - -impl, Y: Render> Default for Bsp { - fn default () -> Self { - Self::Null(Default::default()) - } -} - -impl, Y: Render> Render for Bsp { - fn min_size (&self, to: E::Size) -> Perhaps { - Ok(Some(match self { - Self::Null(_) => [0.into(), 0.into()].into(), - Self::S(a, b) => { - let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - [a.w().max(b.w()), a.h() + b.h()].into() - }, - Self::E(a, b) => { - let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - [a.w() + b.w(), a.h().max(b.h())].into() - }, - Self::W(a, b) => { - let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - [a.w() + b.w(), a.h().max(b.h())].into() - }, - Self::N(a, b) => { - let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); - [a.w().max(b.w()), a.h() + b.h()].into() - }, - _ => todo!() - })) - } - fn render (&self, to: &mut E::Output) -> Usually<()> { - let n = [0.into(), 0.into()].into(); - let s = to.area().wh().into(); - Ok(match self { - Self::Null(_) => {}, - Self::S(a, b) => { - let s_a = a.min_size(s)?.unwrap_or(n); - let _ = b.min_size(s)?.unwrap_or(n); - let h = s_a.h().into(); - to.render_in(to.area().clip_h(h).into(), a)?; - to.render_in(to.area().shrink_y(h).push_y(h).into(), b)?; - }, - Self::E(a, b) => { - let s_a = a.min_size(s)?.unwrap_or(n); - let _ = b.min_size(s)?.unwrap_or(n); - let w = s_a.w().into(); - to.render_in(to.area().clip_w(w).into(), a)?; - to.render_in(to.area().push_x(w).shrink_x(w).into(), b)?; - }, - Self::W(a, b) => { - let s_a = a.min_size(s)?.unwrap_or(n); - let _ = b.min_size(s)?.unwrap_or(n); - let w = (to.area().w() - s_a.w()).into(); - to.render_in(to.area().push_x(w).into(), a)?; - to.render_in(to.area().shrink_x(w).into(), b)?; - }, - Self::N(a, b) => { - let s_a = a.min_size(s)?.unwrap_or(n); - let _ = b.min_size(s)?.unwrap_or(n); - let h = to.area().h() - s_a.h(); - to.render_in(to.area().push_y(h).into(), a)?; - to.render_in(to.area().shrink_y(h).into(), b)?; - }, - _ => todo!() - }) - } -} - -impl Render for Stack -where - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> -{ - fn min_size (&self, to: E::Size) -> Perhaps { - match self.1 { - - South => { - let mut w: E::Unit = 0.into(); - let mut h: E::Unit = 0.into(); - (self.0)(&mut |component: &dyn Render| { - let max = to.h().minus(h); - if max > E::Unit::zero() { - let item = Max::y(max, Push::y(h, component)); - let size = item.min_size(to)?.map(|size|size.wh()); - if let Some([width, height]) = size { - h = h + height.into(); - w = w.max(width); - } - } - Ok(()) - })?; - Ok(Some([w, h].into())) - }, - - East => { - let mut w: E::Unit = 0.into(); - let mut h: E::Unit = 0.into(); - (self.0)(&mut |component: &dyn Render| { - let max = to.w().minus(w); - if max > E::Unit::zero() { - let item = Max::x(max, Push::x(h, component)); - let size = item.min_size(to)?.map(|size|size.wh()); - if let Some([width, height]) = size { - w = w + width.into(); - h = h.max(height); - } - } - Ok(()) - })?; - Ok(Some([w, h].into())) - }, - - North => { - let mut w: E::Unit = 0.into(); - let mut h: E::Unit = 0.into(); - (self.0)(&mut |component: &dyn Render| { - let max = to.h().minus(h); - if max > E::Unit::zero() { - let item = Max::y(to.h() - h, component); - let size = item.min_size(to)?.map(|size|size.wh()); - if let Some([width, height]) = size { - h = h + height.into(); - w = w.max(width); - } - } - Ok(()) - })?; - Ok(Some([w, h].into())) - }, - - West => { - let w: E::Unit = 0.into(); - let h: E::Unit = 0.into(); - (self.0)(&mut |component: &dyn Render| { - if w < to.w() { - todo!(); - } - Ok(()) - })?; - Ok(Some([w, h].into())) - }, - } - } - - fn render (&self, to: &mut E::Output) -> Usually<()> { - let area = to.area(); - let mut w = 0.into(); - let mut h = 0.into(); - match self.1 { - South => { - (self.0)(&mut |item| { - if h < area.h() { - let item = Max::y(area.h() - h, Push::y(h, item)); - let show = item.min_size(area.wh().into())?.map(|s|s.wh()); - if let Some([width, height]) = show { - item.render(to)?; - h = h + height; - if width > w { w = width } - }; - } - Ok(()) - })?; - }, - East => { - (self.0)(&mut |item| { - if w < area.w() { - let item = Max::x(area.w() - w, Push::x(w, item)); - let show = item.min_size(area.wh().into())?.map(|s|s.wh()); - if let Some([width, height]) = show { - item.render(to)?; - w = width + w; - if height > h { h = height } - }; - } - Ok(()) - })?; - }, - North => { - (self.0)(&mut |item| { - if h < area.h() { - let show = item.min_size([area.w(), area.h().minus(h)].into())?.map(|s|s.wh()); - if let Some([width, height]) = show { - Shrink::y(height, Push::y(area.h() - height, item)) - .render(to)?; - h = h + height; - if width > w { w = width } - }; - } - Ok(()) - })?; - }, - _ => todo!() - }; - Ok(()) - } -} - -#[cfg(test)] #[test] fn test_bsp () { - // TODO -}