use crate::*; use std::sync::{Arc, atomic::{AtomicUsize, Ordering::Relaxed}}; 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, } // TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small impl Content for Measure { fn render (&self, to: &mut E) { self.x.store(to.area().w().into(), Relaxed); self.y.store(to.area().h().into(), Relaxed); } } 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 new () -> Self { Self { _engine: PhantomData::default(), x: Arc::new(0.into()), y: Arc::new(0.into()), } } pub fn set_w (&self, w: impl Into) -> &Self { self.x.store(w.into(), Relaxed); self } pub fn set_h (&self, h: impl Into) -> &Self { self.y.store(h.into(), Relaxed); self } pub fn set_wh (&self, w: impl Into, h: impl Into) -> &Self { self.set_w(w); self.set_h(h); self } 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 format (&self) -> Arc { format!("{}x{}", self.w(), self.h()).into() } pub fn of > (&self, item: T) -> Bsp, T> { Bsp::b(Fill::xy(self), item) } }