mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
wip: big flat pt.10, down to 33
This commit is contained in:
parent
d01aa7481b
commit
a0175dabc8
17 changed files with 6 additions and 1362 deletions
|
|
@ -331,7 +331,7 @@ pub fn half_block (lower: bool, upper: bool) -> Option<char> {
|
|||
|
||||
//impl<T: Content<Tui>> Render<Tui> for T {}
|
||||
|
||||
impl Render<Tui> for str {
|
||||
impl Render<Tui> for &str {
|
||||
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
|
||||
// TODO: line breaks
|
||||
Ok(Some([self.chars().count() as u16, 1]))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})])
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ render!(<Tui>|self:Groovebox|{
|
|||
|
||||
struct EditStatus<'a, T: Render<Tui>>(&'a Sampler, &'a MidiEditor, usize, T);
|
||||
impl<'a, T: Render<Tui>> Content<Tui> for EditStatus<'a, T> {
|
||||
fn content (&self) -> impl Render<Tui> {
|
||||
fn content (&self) -> Option<impl Render<Tui>> {
|
||||
Some(Split::n(false, 9, col!([
|
||||
row!(|add|{
|
||||
if let Some(sample) = &self.0.mapped[self.2] {
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ pub trait PhraseViewMode: Render<Tui> + HasSize<Tui> + MidiRange + MidiPoint + D
|
|||
}
|
||||
|
||||
impl Content<Tui> for Box<dyn PhraseViewMode> {
|
||||
fn content (&self) -> impl Render<Tui> {
|
||||
fn content (&self) -> Option<impl Render<Tui>> {
|
||||
Some(&(*self))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ render!(<Tui>|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({
|
||||
|
|
|
|||
448
src/space.rs
448
src/space.rs
|
|
@ -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 <N: Coordinate> (self, area: Area<N>, 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<N: Coordinate>: Area<N> {
|
||||
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>) -> [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<E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, PhantomData<E>);
|
||||
|
||||
/// 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<E: Engine> {
|
||||
fn size (&self) -> &Measure<E>;
|
||||
}
|
||||
|
||||
#[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<E: Engine> {
|
||||
_engine: PhantomData<E>,
|
||||
pub x: Arc<AtomicUsize>,
|
||||
pub y: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
pub struct ShowMeasure<'a>(&'a Measure<Tui>);
|
||||
|
||||
pub trait LayoutDebug<E: Engine> {
|
||||
fn debug <W: Render<E>> (other: W) -> DebugOverlay<E, W> {
|
||||
DebugOverlay(Default::default(), other)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DebugOverlay<E: Engine, W: Render<E>>(PhantomData<E>, pub W);
|
||||
|
||||
impl<T: Render<Tui>> Render<Tui> for DebugOverlay<Tui, T> {
|
||||
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<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||
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<E: Engine, T: Render<E>> $Enum<E, T> {
|
||||
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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, W: Render<E>> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E: Engine, T> {
|
||||
/// 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<E: Engine, T: Render<E>> {
|
||||
/// 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<E, A, B>(pub bool, pub Direction, pub E::Unit, A, B, PhantomData<E>)
|
||||
where E: Engine, A: Render<E>, B: Render<E>;
|
||||
|
||||
impl<E: Engine, A: Render<E>, B: Render<E>> Split<E, A, B> {
|
||||
#[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<E: Engine, X: Render<E>, Y: Render<E>> {
|
||||
/// X is north of Y
|
||||
N(Option<X>, Option<Y>),
|
||||
/// X is south of Y
|
||||
S(Option<X>, Option<Y>),
|
||||
/// X is east of Y
|
||||
E(Option<X>, Option<Y>),
|
||||
/// X is west of Y
|
||||
W(Option<X>, Option<Y>),
|
||||
/// X is above Y
|
||||
A(Option<X>, Option<Y>),
|
||||
/// X is below Y
|
||||
B(Option<X>, Option<Y>),
|
||||
/// Should be avoided.
|
||||
Null(PhantomData<E>),
|
||||
}
|
||||
|
||||
impl<E: Engine, X: Render<E>, Y: Render<E>> Bsp<E, X, Y> {
|
||||
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<E>)->Usually<()>)->Usually<()>
|
||||
>(pub F, pub Direction, PhantomData<E>);
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||
> Stack<E, F> {
|
||||
#[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<E, F>(pub F, pub Direction, pub u64, PhantomData<E>)
|
||||
where
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>;
|
||||
|
||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||
pub enum Align<E: Engine, T: Render<E>> {
|
||||
_Unused(PhantomData<E>),
|
||||
/// 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)
|
||||
}
|
||||
|
|
@ -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<CallbackCollection<'a, E>> for Collect<'a, E, N> {
|
||||
fn from (callback: CallbackCollection<'a, E>) -> Self {
|
||||
Self::Callback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine, const N: usize> From<SliceCollection<'a, E>> for Collect<'a, E, N> {
|
||||
fn from (slice: SliceCollection<'a, E>) -> Self {
|
||||
Self::Slice(slice)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine, const N: usize> From<ArrayCollection<'a, E, N>> 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<E>)->Usually<()>);
|
||||
|
||||
//type IteratorCollection<'a, E> =
|
||||
//&'a mut dyn Iterator<Item = dyn Render<E>>;
|
||||
|
||||
type SliceCollection<'a, E> =
|
||||
&'a [&'a dyn Render<E>];
|
||||
|
||||
type ArrayCollection<'a, E, const N: usize> =
|
||||
[&'a dyn Render<E>; 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<E>;
|
||||
fn next (&mut self) -> Option<Self::Item> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, A: Render<E>> Render<E> for When<E, A> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Either<E, A, B> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
impl<T> Coordinate for T where T: Send + Sync + Copy
|
||||
+ Add<Self, Output=Self>
|
||||
+ Sub<Self, Output=Self>
|
||||
+ Mul<Self, Output=Self>
|
||||
+ Div<Self, Output=Self>
|
||||
+ Ord + PartialEq + Eq
|
||||
+ Debug + Display + Default
|
||||
+ From<u16> + Into<u16>
|
||||
+ Into<usize>
|
||||
+ Into<f64>
|
||||
{}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
impl<
|
||||
E: Engine,
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||
> Layers<E, F> {
|
||||
#[inline]
|
||||
pub fn new (build: F) -> Self {
|
||||
Self(build, Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, F> Render<E> for Layers<E, F>
|
||||
where
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||
{
|
||||
fn min_size (&self, area: E::Size) -> Perhaps<E::Size> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl<E: Engine, I: Iterator<Item=T>+Send+Sync, T, R: Render<E>> LayoutMapReduce<E, I, T, R> for E {}
|
||||
|
||||
pub trait LayoutMapReduce<E: Engine, I: Iterator<Item = T>+Send+Sync, T, R: Render<E>> {
|
||||
fn map <F: Fn(T)->R> (iterator: I, callback: F) -> Map<E, T, I, R, F> {
|
||||
Map(Default::default(), iterator, callback)
|
||||
}
|
||||
fn reduce <F: Fn(&dyn Render<E>, T)->R+Send+Sync> (iterator: I, callback: F) -> Reduce<E, T, I, R, F> {
|
||||
Reduce(Default::default(), iterator, callback)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Map<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(T)->R>(
|
||||
PhantomData<E>,
|
||||
I,
|
||||
F
|
||||
);
|
||||
|
||||
pub struct Reduce<E: Engine, T, I: Iterator<Item=T>, R: Render<E>, F: Fn(&dyn Render<E>, T)->R>(
|
||||
PhantomData<(E, R)>,
|
||||
I,
|
||||
F
|
||||
);
|
||||
|
||||
impl<E: Engine, T, I: Iterator<Item=T>+Send+Sync, R: Render<E>, F: Fn(&dyn Render<E>, T)->R+Send+Sync> Render<E> for Reduce<E, T, I, R, F> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
todo!()
|
||||
}
|
||||
fn render (&self, to: &mut E::Output) -> Usually<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
impl<E: Engine> LayoutDebug<E> for E {}
|
||||
|
||||
impl<E: Engine> Clone for Measure<E> {
|
||||
fn clone (&self) -> Self {
|
||||
Self {
|
||||
_engine: Default::default(),
|
||||
x: self.x.clone(),
|
||||
y: self.y.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> std::fmt::Debug for Measure<E> {
|
||||
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<E: Engine> Measure<E> {
|
||||
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<usize>) { self.x.store(w.into(), Relaxed) }
|
||||
pub fn set_h (&self, h: impl Into<usize>) { self.y.store(h.into(), Relaxed) }
|
||||
pub fn set_wh (&self, w: impl Into<usize>, h: impl Into<usize>) { 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<Tui> for Measure<Tui> {
|
||||
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<Tui> {
|
||||
pub fn debug (&self) -> ShowMeasure {
|
||||
ShowMeasure(&self)
|
||||
}
|
||||
}
|
||||
|
||||
render!(<Tui>|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))
|
||||
))
|
||||
})));
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
impl<E: Engine, T: Render<E>> Push<E, T> {
|
||||
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<E: Engine, T: Render<E>> Render<E> for Push<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Pull<E, T> {
|
||||
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<E: Engine, T: Render<E>> Render<E> for Pull<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Padding<E, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Padding<E, T> {
|
||||
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<E: Engine, T: Render<E>> Margin<E, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Margin<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Align<E, T> {
|
||||
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<E: Engine, T: Render<E>, N: Coordinate, R: Area<N> + From<[N;4]>> (align: &Align<E, T>, outer: R, inner: R) -> Option<R> {
|
||||
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<E: Engine, T: Render<E>> Render<E> for Align<E, T> {
|
||||
fn min_size (&self, outer_area: E::Size) -> Perhaps<E::Size> {
|
||||
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())?
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
use crate::*;
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
impl<N: Coordinate> Size<N> for (N, N) {
|
||||
fn x (&self) -> N { self.0 }
|
||||
fn y (&self) -> N { self.1 }
|
||||
}
|
||||
|
||||
impl<N: Coordinate> Size<N> for [N;2] {
|
||||
fn x (&self) -> N { self[0] }
|
||||
fn y (&self) -> N { self[1] }
|
||||
}
|
||||
|
||||
impl<N: Coordinate> Area<N> 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<N: Coordinate> Area<N> 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<E: Engine, T: Render<E>> Shrink<E, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Grow<E, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Shrink<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Render<E> for Grow<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, W: Render<E>> Fill<E, W> {
|
||||
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<E: Engine, W: Render<E>> Render<E> for Fill<E, W> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Fixed<E, T> {
|
||||
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<E: Engine, T: Render<E>> Render<E> for Fixed<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Min<E, T> {
|
||||
pub fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Min<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, T: Render<E>> Max<E, T> {
|
||||
fn inner (&self) -> &T {
|
||||
match self {
|
||||
Self::X(_, i) => i,
|
||||
Self::Y(_, i) => i,
|
||||
Self::XY(_, _, i) => i,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, T: Render<E>> Render<E> for Max<E, T> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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(()))
|
||||
}
|
||||
}
|
||||
|
|
@ -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<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Split<E, A, B> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, X: Render<E>, Y: Render<E>> Default for Bsp<E, X, Y> {
|
||||
fn default () -> Self {
|
||||
Self::Null(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine, X: Render<E>, Y: Render<E>> Render<E> for Bsp<E, X, Y> {
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
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<E: Engine, F> Render<E> for Stack<E, F>
|
||||
where
|
||||
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
|
||||
{
|
||||
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
|
||||
match self.1 {
|
||||
|
||||
South => {
|
||||
let mut w: E::Unit = 0.into();
|
||||
let mut h: E::Unit = 0.into();
|
||||
(self.0)(&mut |component: &dyn Render<E>| {
|
||||
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<E>| {
|
||||
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<E>| {
|
||||
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<E>| {
|
||||
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue