diff --git a/layout/src/measure.rs b/layout/src/measure.rs index afb5785b..584bbef4 100644 --- a/layout/src/measure.rs +++ b/layout/src/measure.rs @@ -1,6 +1,6 @@ use crate::*; use std::sync::{Arc, atomic::{AtomicUsize, Ordering::Relaxed}}; -use ratatui::prelude::{Style, Color}; +//use ratatui::prelude::{Style, Color}; // TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small @@ -81,42 +81,42 @@ impl Measure { //impl ContentDebug for E {} -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 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) - } -} +//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)) - )) -}))); +//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)) + //)) +//}))); -pub struct ShowMeasure<'a>(&'a Measure); +//pub struct ShowMeasure<'a>(&'a Measure); -pub struct DebugOverlay>(PhantomData, pub W); +//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()))) - } -} +//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()))) + //} +//} diff --git a/layout/src/transform.rs b/layout/src/transform.rs index aa73e021..c21345e2 100644 --- a/layout/src/transform.rs +++ b/layout/src/transform.rs @@ -151,67 +151,77 @@ transform_xy_unit!(|self: Padding, area|{ [area.x() + dx, area.y() + dy, area.w().minus(dy + dy), area.h().minus(dy + dy), ] }); -content_enum!(Align: Center, X, Y, NW, N, NE, E, SE, S, SW, W); -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) } -} +#[derive(Default, Debug, Copy, Clone)] +pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } -fn align, N: Coordinate, R: Area + From<[N;4]>> (align: &Align, outer: R, content: R) -> Option { - if outer.w() < content.w() || outer.h() < content.h() { - None - } else { - let [ox, oy, ow, oh] = outer.xywh(); - let [ix, iy, iw, ih] = content.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!() - }) - } +pub struct Align>(Alignment, T, PhantomData); + +impl> Align { + pub fn c (w: T) -> Self { Self(Alignment::Center, w, Default::default()) } + pub fn x (w: T) -> Self { Self(Alignment::X, w, Default::default()) } + pub fn y (w: T) -> Self { Self(Alignment::Y, w, Default::default()) } + pub fn n (w: T) -> Self { Self(Alignment::N, w, Default::default()) } + pub fn s (w: T) -> Self { Self(Alignment::S, w, Default::default()) } + pub fn e (w: T) -> Self { Self(Alignment::E, w, Default::default()) } + pub fn w (w: T) -> Self { Self(Alignment::W, w, Default::default()) } + pub fn nw (w: T) -> Self { Self(Alignment::NW, w, Default::default()) } + pub fn sw (w: T) -> Self { Self(Alignment::SW, w, Default::default()) } + pub fn ne (w: T) -> Self { Self(Alignment::NE, w, Default::default()) } + pub fn se (w: T) -> Self { Self(Alignment::SE, w, Default::default()) } } impl> Content for Align { fn area (&self, outer: E::Area) -> E::Area { - let inner = Content::area(&self.content(), outer); - let (oc, ic) = (outer.center(), inner.center()); - match self { - Self::Center(_) => [0, 0, 0, 0], - Self::X(_) => [0, 0, 0, 0], - Self::Y(_) => [0, 0, 0, 0], - _ => [0, 0, 0, 0] - }.into() + align_areas(self.0, outer.xywh(), Content::area(&self.content(), outer).xywh()).into() } fn render (&self, render: &mut E::Output) { - let outer = render.area(); - let content = self.content(); - let inner = Content::area(&content, outer); - let aligned = match self { - Self::Center(_) => { - let oc = outer.center(); - let ic = inner.center(); - } - } - if let Some(aligned) = align(&self, outer.into(), inner.into()) { - to.place(aligned, &content) - } + render.place(self.area(render.area()), &self.content()) } } + +pub fn align_areas(alignment: Alignment, on: [N;4], it: [N;4]) -> [N;4] { + let [cfx, cfy] = on.center(); + let [cmx, cmy] = it.center(); + let center = |cf, cm, m: N|if cf >= cm { m + (cf - cm) } else { m.minus(cm - cf) }; + let center_x = center(cfx, cmx, it.x()); + let center_y = center(cfy, cmy, it.y()); + let east_x = on.x() + on.w().minus(it.w()); + let south_y = on.y() + on.h().minus(it.h()); + match alignment { + Alignment::Center => [center_x, center_y, it.w(), it.h()], + Alignment::X => [center_x, it.y(), it.w(), it.h()], + Alignment::Y => [it.x(), center_y, it.w(), it.h()], + + Alignment::NW => [on.x(), on.y(), it.w(), it.h()], + Alignment::N => [center_x, on.y(), it.w(), it.h()], + Alignment::NE => [east_x, on.y(), it.w(), it.h()], + Alignment::E => [east_x, center_y, it.w(), it.h()], + Alignment::SE => [east_x, south_y, it.w(), it.h()], + Alignment::S => [center_x, south_y, it.w(), it.h()], + Alignment::SW => [on.x(), south_y, it.w(), it.h()], + Alignment::W => [on.x(), center_y, it.w(), it.h()], + } +} + +//fn align, N: Coordinate, R: Area + From<[N;4]>> (align: &Align, outer: R, content: R) -> Option { + //if outer.w() < content.w() || outer.h() < content.h() { + //None + //} else { + //let [ox, oy, ow, oh] = outer.xywh(); + //let [ix, iy, iw, ih] = content.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!() + //}) + //} +//}