mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-02-22 18:59:02 +01:00
refactor: flatten this too
This commit is contained in:
parent
b4ebdb8ff8
commit
5d61cc6c5f
34 changed files with 3053 additions and 3167 deletions
|
|
@ -1,896 +0,0 @@
|
|||
use crate::*;
|
||||
use Alignment::*;
|
||||
|
||||
impl Coord for u16 {
|
||||
fn plus (self, other: Self) -> Self { self.saturating_add(other) }
|
||||
}
|
||||
|
||||
impl<N: Coord> HasXY<N> for XY<N> {
|
||||
fn x (&self) -> N { self.0 }
|
||||
fn y (&self) -> N { self.1 }
|
||||
}
|
||||
|
||||
impl<N: Coord> HasXY<N> for XYWH<N> {
|
||||
fn x (&self) -> N { self.0 }
|
||||
fn y (&self) -> N { self.1 }
|
||||
}
|
||||
|
||||
impl<O: Out> HasXY<O::Unit> for O {
|
||||
// X coordinate of output area
|
||||
#[inline] fn x (&self) -> O::Unit { self.area().x() }
|
||||
// Y coordinate of output area
|
||||
#[inline] fn y (&self) -> O::Unit { self.area().y() }
|
||||
}
|
||||
|
||||
impl<N: Coord> HasWH<N> for WH<N> {
|
||||
fn w (&self) -> N { self.0 }
|
||||
fn h (&self) -> N { self.1 }
|
||||
}
|
||||
|
||||
impl<N: Coord> HasWH<N> for XYWH<N> {
|
||||
fn w (&self) -> N { self.2 }
|
||||
fn h (&self) -> N { self.3 }
|
||||
}
|
||||
|
||||
impl<O: Out> HasWH<O::Unit> for O {
|
||||
// Width of output area
|
||||
#[inline] fn w (&self) -> O::Unit { self.area().w() }
|
||||
// Height of output area
|
||||
#[inline] fn h (&self) -> O::Unit { self.area().h() }
|
||||
}
|
||||
|
||||
impl<N: Coord> WH<N> {
|
||||
pub fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w), self.h()] }
|
||||
pub fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h)] }
|
||||
pub fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
|
||||
if self.w() < w || self.h() < h { return Err(format!("min {w}x{h}").into()) }
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
impl<N: Coord> XYWH<N> {
|
||||
pub fn zero () -> Self {
|
||||
Self(0.into(), 0.into(), 0.into(), 0.into())
|
||||
}
|
||||
pub fn x2 (&self) -> N {
|
||||
self.x().plus(self.w())
|
||||
}
|
||||
pub fn y2 (&self) -> N {
|
||||
self.y().plus(self.h())
|
||||
}
|
||||
pub fn with_w (&self, w: N) -> XYWH<N> {
|
||||
Self(self.x(), self.y(), w, self.h())
|
||||
}
|
||||
pub fn with_h (&self, h: N) -> XYWH<N> {
|
||||
Self(self.x(), self.y(), self.w(), h)
|
||||
}
|
||||
pub fn lrtb (&self) -> [N;4] {
|
||||
[self.x(), self.x2(), self.y(), self.y2()]
|
||||
}
|
||||
pub fn clipped_w (&self, w: N) -> XYWH<N> {
|
||||
Self(self.x(), self.y(), self.w().min(w), self.h())
|
||||
}
|
||||
pub fn clipped_h (&self, h: N) -> XYWH<N> {
|
||||
Self(self.x(), self.y(), self.w(), self.h().min(h))
|
||||
}
|
||||
pub fn clipped (&self, wh: WH<N>) -> XYWH<N> {
|
||||
Self(self.x(), self.y(), wh.w(), wh.h())
|
||||
}
|
||||
/// Iterate over every covered X coordinate.
|
||||
pub fn iter_x (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
|
||||
let Self(x, _, w, _) = *self;
|
||||
x..(x+w)
|
||||
}
|
||||
/// Iterate over every covered Y coordinate.
|
||||
pub fn iter_y (&self) -> impl Iterator<Item = N> where N: std::iter::Step {
|
||||
let Self(_, y, _, h) = *self;
|
||||
y..(y+h)
|
||||
}
|
||||
pub fn center (&self) -> XY<N> {
|
||||
let Self(x, y, w, h) = self;
|
||||
XY(self.x().plus(self.w()/2.into()), self.y().plus(self.h()/2.into()))
|
||||
}
|
||||
pub fn centered (&self) -> XY<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XY(x.minus(w/2.into()), y.minus(h/2.into()))
|
||||
}
|
||||
pub fn centered_x (&self, n: N) -> XYWH<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XYWH((x.plus(w / 2.into())).minus(n / 2.into()), y.plus(h / 2.into()), n, 1.into())
|
||||
}
|
||||
pub fn centered_y (&self, n: N) -> XYWH<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XYWH(x.plus(w / 2.into()), (y.plus(h / 2.into())).minus(n / 2.into()), 1.into(), n)
|
||||
}
|
||||
pub fn centered_xy (&self, [n, m]: [N;2]) -> XYWH<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XYWH((x.plus(w / 2.into())).minus(n / 2.into()), (y.plus(h / 2.into())).minus(m / 2.into()), n, m)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for T {}
|
||||
|
||||
impl<'a, O: Out> AsRef<dyn Draw<O> + 'a> for dyn Content<O> + 'a {
|
||||
fn as_ref (&self) -> &(dyn Draw<O> + 'a) { self }
|
||||
}
|
||||
|
||||
impl<'a, O: Out> AsRef<dyn Layout<O> + 'a> for dyn Content<O> + 'a {
|
||||
fn as_ref (&self) -> &(dyn Layout<O> + 'a) { self }
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for () {
|
||||
fn draw (&self, _: &mut O) {}
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for fn(&mut O) {
|
||||
fn draw (&self, to: &mut O) { (*self)(to) }
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for Box<dyn Draw<O>> {
|
||||
fn draw (&self, to: &mut O) { (**self).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for &D {
|
||||
fn draw (&self, to: &mut O) { (*self).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for &mut D {
|
||||
fn draw (&self, to: &mut O) { (**self).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for Arc<D> {
|
||||
fn draw (&self, to: &mut O) { (**self).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for RwLock<D> {
|
||||
fn draw (&self, to: &mut O) { self.read().unwrap().draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, D: Draw<O>> Draw<O> for Option<D> {
|
||||
fn draw (&self, to: &mut O) { if let Some(draw) = self { draw.draw(to) } }
|
||||
}
|
||||
|
||||
//impl<O: Out, T: HasContent<O>> Draw<O> for T {
|
||||
//fn draw (&self, to: &mut O) {
|
||||
//let area = to.area();
|
||||
//*to.area_mut() = self.0;
|
||||
//self.content().draw(to);
|
||||
//*to.area_mut() = area;
|
||||
//}
|
||||
//}
|
||||
|
||||
impl<O: Out, T: Content<O>, F: Fn()->T> Lazy<O, T, F> {
|
||||
pub const fn new (thunk: F) -> Self {
|
||||
Self(thunk, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, F: Fn(&mut O)> Thunk<O, F> {
|
||||
pub const fn new (draw: F) -> Self {
|
||||
Self(PhantomData, draw)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, F: Fn(&mut O)> Layout<O> for Thunk<O, F> {}
|
||||
|
||||
impl<O: Out, F: Fn(&mut O)> Draw<O> for Thunk<O, F> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(self.1)(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> Memo<T, U> {
|
||||
pub fn new (value: T, view: U) -> Self { Self { value, view: Arc::new(view.into()) } }
|
||||
pub fn update <R> (&mut self, newval: T, draw: impl Fn(&mut U, &T, &T)->R) -> Option<R> {
|
||||
if newval != self.value {
|
||||
let result = draw(&mut*self.view.write().unwrap(), &newval, &self.value);
|
||||
self.value = newval;
|
||||
return Some(result);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn split_fixed <N: Coord> (self, area: XYWH<N>, a: N) -> (XYWH<N>, XYWH<N>) {
|
||||
let XYWH(x, y, w, h) = area;
|
||||
match self {
|
||||
North => (XYWH(x, y.plus(h).minus(a), w, a), XYWH(x, y, w, h.minus(a))),
|
||||
South => (XYWH(x, y, w, a), XYWH(x, y.plus(a), w, h.minus(a))),
|
||||
East => (XYWH(x, y, a, h), XYWH(x.plus(a), y, w.minus(a), h)),
|
||||
West => (XYWH(x.plus(w).minus(a), y, a, h), XYWH(x, y, w.minus(a), h)),
|
||||
Above | Below => (area, area)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Has<Measure<E>>> Measured<E> for T {
|
||||
fn measure (&self) -> &Measure<E> {
|
||||
self.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Clone for Measure<O> {
|
||||
fn clone (&self) -> Self {
|
||||
Self { __: Default::default(), x: self.x.clone(), y: self.y.clone(), }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Layout<O> for Measure<O> {}
|
||||
|
||||
impl<O: Out> PartialEq for Measure<O> {
|
||||
fn eq (&self, other: &Self) -> bool {
|
||||
self.x.load(Relaxed) == other.x.load(Relaxed) &&
|
||||
self.y.load(Relaxed) == other.y.load(Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
|
||||
impl<O: Out> Draw<O> for Measure<O> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
self.x.store(to.area().w().into(), Relaxed);
|
||||
self.y.store(to.area().h().into(), Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Debug for Measure<O> {
|
||||
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<O: Out> Measure<O> {
|
||||
pub fn set_w (&self, w: impl Into<usize>) -> &Self { self.x.store(w.into(), Relaxed); self }
|
||||
pub fn set_h (&self, h: impl Into<usize>) -> &Self { self.y.store(h.into(), Relaxed); self }
|
||||
pub fn set_wh (&self, w: impl Into<usize>, h: impl Into<usize>) -> &Self { self.set_w(w); self.set_h(h); self }
|
||||
pub fn format (&self) -> Arc<str> { format!("{}x{}", self.w(), self.h()).into() }
|
||||
pub fn of <T: Draw<O>> (&self, item: T) -> Bsp<Fill<&Self>, T> { Bsp::b(Fill::XY(self), item) }
|
||||
pub fn new (x: O::Unit, y: O::Unit) -> Self {
|
||||
Self { __: PhantomData::default(), x: Arc::new(x.atomic()), y: Arc::new(y.atomic()), }
|
||||
}
|
||||
}
|
||||
|
||||
/// FIXME don't convert to u16 specifically
|
||||
impl<O: Out> HasWH<O::Unit> for Measure<O> {
|
||||
fn w (&self) -> O::Unit { (self.x.load(Relaxed) as u16).into() }
|
||||
fn h (&self) -> O::Unit { (self.y.load(Relaxed) as u16).into() }
|
||||
}
|
||||
impl<O: Out> From<WH<O::Unit>> for Measure<O> {
|
||||
fn from (WH(x, y): WH<O::Unit>) -> Self { Self::new(x, y) }
|
||||
}
|
||||
|
||||
impl<O: Out> Layout<O> for () {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { a.x() }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { a.y() }
|
||||
fn layout_w (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout_w_min (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout_w_max (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout_h (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout_h_min (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout_h_max (&self, _: XYWH<O::Unit>) -> O::Unit { 0.into() }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { XYWH(a.x(), a.y(), 0.into(), 0.into()) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &L {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_x(a) }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_y(a) }
|
||||
fn layout_w (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_w(a) }
|
||||
fn layout_w_min (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_w_min(a) }
|
||||
fn layout_w_max (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_w_max(a) }
|
||||
fn layout_h (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_h(a) }
|
||||
fn layout_h_min (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_h_min(a) }
|
||||
fn layout_h_max (&self, a: XYWH<O::Unit>) -> O::Unit { (*self).layout_h_max(a) }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { (*self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &mut L {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_x(a) }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_y(a) }
|
||||
fn layout_w (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w(a) }
|
||||
fn layout_w_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_min(a) }
|
||||
fn layout_w_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_max(a) }
|
||||
fn layout_h (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h(a) }
|
||||
fn layout_h_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_min(a) }
|
||||
fn layout_h_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_max(a) }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { (**self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Arc<L> {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_x(a) }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_y(a) }
|
||||
fn layout_w (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w(a) }
|
||||
fn layout_w_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_min(a) }
|
||||
fn layout_w_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_max(a) }
|
||||
fn layout_h (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h(a) }
|
||||
fn layout_h_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_min(a) }
|
||||
fn layout_h_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_max(a) }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { (**self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out> Layout<O> for Box<dyn Layout<O>> {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_x(a) }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_y(a) }
|
||||
fn layout_w (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w(a) }
|
||||
fn layout_w_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_min(a) }
|
||||
fn layout_w_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_w_max(a) }
|
||||
fn layout_h (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h(a) }
|
||||
fn layout_h_min (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_min(a) }
|
||||
fn layout_h_max (&self, a: XYWH<O::Unit>) -> O::Unit { (**self).layout_h_max(a) }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { (**self).layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for RwLock<L> {
|
||||
fn layout_x (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_x(a) }
|
||||
fn layout_y (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_y(a) }
|
||||
fn layout_w (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_w(a) }
|
||||
fn layout_w_min (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_w_min(a) }
|
||||
fn layout_w_max (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_w_max(a) }
|
||||
fn layout_h (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_h(a) }
|
||||
fn layout_h_min (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_h_min(a) }
|
||||
fn layout_h_max (&self, a: XYWH<O::Unit>) -> O::Unit { self.read().unwrap().layout_h_max(a) }
|
||||
fn layout (&self, a: XYWH<O::Unit>) -> XYWH<O::Unit> { self.read().unwrap().layout(a) }
|
||||
}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> {
|
||||
fn layout_x (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_x(to)).unwrap_or(to.x()) }
|
||||
fn layout_y (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_y(to)).unwrap_or(to.y()) }
|
||||
fn layout_w_min (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_w_min(to)).unwrap_or(0.into()) }
|
||||
fn layout_w_max (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_w_max(to)).unwrap_or(0.into()) }
|
||||
fn layout_w (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_w(to)).unwrap_or(0.into()) }
|
||||
fn layout_h_min (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_h_min(to)).unwrap_or(0.into()) }
|
||||
fn layout_h_max (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_h_max(to)).unwrap_or(0.into()) }
|
||||
fn layout_h (&self, to: XYWH<O::Unit>) -> O::Unit { self.as_ref().map(|c|c.layout_h(to)).unwrap_or(0.into()) }
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> {
|
||||
let xywh = XYWH(self.layout_x(to), self.layout_y(to), self.layout_w(to), self.layout_h(to));
|
||||
self.as_ref().map(|c|c.layout(xywh)).unwrap_or(XYWH(to.x(), to.y(), 0.into(), 0.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, D: Content<O>> HasContent<O> for Bounded<O, D> {
|
||||
fn content (&self) -> impl Content<O> {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Bounded<O, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let area = to.area();
|
||||
*to.area_mut() = self.0;
|
||||
self.1.draw(to);
|
||||
*to.area_mut() = area;
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Content<O>> When<O, T> {
|
||||
/// Create a binary condition.
|
||||
pub const fn new (c: bool, a: T) -> Self { Self(c, a, PhantomData) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for When<O, T> {
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> {
|
||||
let Self(cond, item, ..) = self;
|
||||
if *cond { item.layout(to) } else { XYWH::<O::Unit>::zero().into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Content<O>> Draw<O> for When<O, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let Self(cond, item, ..) = self;
|
||||
if *cond { Bounded(self.layout(to.area()), item).draw(to) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, A: Content<E>, B: Content<E>> Either<E, A, B> {
|
||||
/// Create a ternary view condition.
|
||||
pub const fn new (c: bool, a: A, b: B) -> Self {
|
||||
Self(c, a, b, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, A: Layout<E>, B: Layout<E>> Layout<E> for Either<E, A, B> {
|
||||
fn layout (&self, to: XYWH<E::Unit>) -> XYWH<E::Unit> {
|
||||
let Self(cond, a, b, ..) = self;
|
||||
if *cond { a.layout(to) } else { b.layout(to) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, A: Content<E>, B: Content<E>> Draw<E> for Either<E, A, B> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
let Self(cond, a, b, ..) = self;
|
||||
let area = self.layout(to.area());
|
||||
if *cond { Bounded(area, a).draw(to) } else { Bounded(area, b).draw(to) }
|
||||
}
|
||||
}
|
||||
|
||||
push_pull!(Push: plus);
|
||||
|
||||
push_pull!(Pull: minus);
|
||||
|
||||
layout_op_xy!(0: Fill);
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Fill<T> {
|
||||
fn layout_x (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dx() { area.x() } else { self.inner().layout_x(area) } }
|
||||
fn layout_y (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dy() { area.y() } else { self.inner().layout_y(area) } }
|
||||
fn layout_w (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dx() { area.w() } else { self.inner().layout_w(area) } }
|
||||
fn layout_w_min (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dx() { area.w() } else { self.inner().layout_w_min(area) } }
|
||||
fn layout_w_max (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dx() { area.w() } else { self.inner().layout_w_max(area) } }
|
||||
fn layout_h (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dy() { area.h() } else { self.inner().layout_h(area) } }
|
||||
fn layout_h_min (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dy() { area.h() } else { self.inner().layout_h_min(area) } }
|
||||
fn layout_h_max (&self, area: XYWH<O::Unit>) -> O::Unit { if self.dy() { area.h() } else { self.inner().layout_h_max(area) } }
|
||||
}
|
||||
|
||||
impl<A> Fill<A> {
|
||||
#[inline] pub const fn dx (&self) -> bool { matches!(self, Self::X(_) | Self::XY(_)) }
|
||||
#[inline] pub const fn dy (&self) -> bool { matches!(self, Self::Y(_) | Self::XY(_)) }
|
||||
}
|
||||
|
||||
layout_op_xy!(1 opt: Fixed);
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Fixed<O::Unit, T> {
|
||||
fn layout_w (&self, area: XYWH<O::Unit>) -> O::Unit { self.dx().unwrap_or(self.inner().layout_w(area)) }
|
||||
fn layout_w_min (&self, area: XYWH<O::Unit>) -> O::Unit { self.dx().unwrap_or(self.inner().layout_w_min(area)) }
|
||||
fn layout_w_max (&self, area: XYWH<O::Unit>) -> O::Unit { self.dx().unwrap_or(self.inner().layout_w_max(area)) }
|
||||
fn layout_h (&self, area: XYWH<O::Unit>) -> O::Unit { self.dy().unwrap_or(self.inner().layout_h(area)) }
|
||||
fn layout_h_min (&self, area: XYWH<O::Unit>) -> O::Unit { self.dy().unwrap_or(self.inner().layout_h_min(area)) }
|
||||
fn layout_h_max (&self, area: XYWH<O::Unit>) -> O::Unit { self.dy().unwrap_or(self.inner().layout_h_max(area)) }
|
||||
}
|
||||
|
||||
layout_op_xy!(1 opt: Max);
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Max<E::Unit, T> {
|
||||
fn layout (&self, area: XYWH<E::Unit>) -> XYWH<E::Unit> {
|
||||
let XYWH(x, y, w, h) = self.inner().layout(area);
|
||||
match self {
|
||||
Self::X(mw, _) => XYWH(x, y, w.min(*mw), h ),
|
||||
Self::Y(mh, _) => XYWH(x, y, w, h.min(*mh)),
|
||||
Self::XY(mw, mh, _) => XYWH(x, y, w.min(*mw), h.min(*mh)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout_op_xy!(1 opt: Min);
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Min<E::Unit, T> {
|
||||
fn layout (&self, area: XYWH<E::Unit>) -> XYWH<E::Unit> {
|
||||
let XYWH(x, y, w, h) = self.inner().layout(area);
|
||||
match self {
|
||||
Self::X(mw, _) => XYWH(x, y, w.max(*mw), h),
|
||||
Self::Y(mh, _) => XYWH(x, y, w, h.max(*mh)),
|
||||
Self::XY(mw, mh, _) => XYWH(x, y, w.max(*mw), h.max(*mh)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layout_op_xy!(1 opt: Expand);
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Expand<O::Unit, T> {
|
||||
fn layout_w (&self, to: XYWH<O::Unit>) -> O::Unit {
|
||||
self.inner().layout_w(to).plus(self.dx().unwrap_or_default())
|
||||
}
|
||||
fn layout_h (&self, to: XYWH<O::Unit>) -> O::Unit {
|
||||
self.inner().layout_w(to).plus(self.dy().unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: why they differ?
|
||||
|
||||
layout_op_xy!(1 opt: Shrink);
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Shrink<E::Unit, T> {
|
||||
fn layout (&self, to: XYWH<E::Unit>) -> XYWH<E::Unit> {
|
||||
let area = self.inner().layout(to);
|
||||
let dx = self.dx().unwrap_or_default();
|
||||
let dy = self.dy().unwrap_or_default();
|
||||
XYWH(area.x(), area.y(), area.w().minus(dx), area.h().minus(dy))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Align<T> {
|
||||
#[inline] pub const fn c (a: T) -> Self { Self(Alignment::Center, a) }
|
||||
#[inline] pub const fn x (a: T) -> Self { Self(Alignment::X, a) }
|
||||
#[inline] pub const fn y (a: T) -> Self { Self(Alignment::Y, a) }
|
||||
#[inline] pub const fn n (a: T) -> Self { Self(Alignment::N, a) }
|
||||
#[inline] pub const fn s (a: T) -> Self { Self(Alignment::S, a) }
|
||||
#[inline] pub const fn e (a: T) -> Self { Self(Alignment::E, a) }
|
||||
#[inline] pub const fn w (a: T) -> Self { Self(Alignment::W, a) }
|
||||
#[inline] pub const fn nw (a: T) -> Self { Self(Alignment::NW, a) }
|
||||
#[inline] pub const fn sw (a: T) -> Self { Self(Alignment::SW, a) }
|
||||
#[inline] pub const fn ne (a: T) -> Self { Self(Alignment::NE, a) }
|
||||
#[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Align<T> {
|
||||
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), &self.1).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Align<T> {
|
||||
fn layout_x (&self, to: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
NW | W | SW => to.x(),
|
||||
N | Center | S => to.x().plus(to.w() / 2.into()).minus(self.1.layout_w(to) / 2.into()),
|
||||
NE | E | SE => to.x().plus(to.w()).minus(self.1.layout_w(to)),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
fn layout_y (&self, to: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
NW | N | NE => to.y(),
|
||||
W | Center | E => to.y().plus(to.h() / 2.into()).minus(self.1.layout_h(to) / 2.into()),
|
||||
SW | S | SE => to.y().plus(to.h()).minus(self.1.layout_h(to)),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, A> Pad<U, A> {
|
||||
#[inline] pub const fn inner (&self) -> &A {
|
||||
use Pad::*;
|
||||
match self { X(_, c) | Y(_, c) | XY(_, _, c) => c, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: Coord, T> Pad<U, T> {
|
||||
#[inline] pub fn dx (&self) -> U {
|
||||
use Pad::*;
|
||||
match self { X(x, _) => *x, Y(_, _) => 0.into(), XY(x, _, _) => *x, }
|
||||
}
|
||||
#[inline] pub fn dy (&self) -> U {
|
||||
use Pad::*;
|
||||
match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Layout<O>> Layout<O> for Pad<O::Unit, T> {
|
||||
fn layout_x (&self, area: XYWH<O::Unit>) -> O::Unit { area.x().plus(self.dx()) }
|
||||
fn layout_y (&self, area: XYWH<O::Unit>) -> O::Unit { area.x().plus(self.dx()) }
|
||||
fn layout_w (&self, area: XYWH<O::Unit>) -> O::Unit { area.w().minus(self.dx() * 2.into()) }
|
||||
fn layout_h (&self, area: XYWH<O::Unit>) -> O::Unit { area.h().minus(self.dy() * 2.into()) }
|
||||
}
|
||||
|
||||
impl<Head, Tail> Bsp<Head, Tail> {
|
||||
#[inline] pub const fn n (a: Head, b: Tail) -> Self { Self(North, a, b) }
|
||||
#[inline] pub const fn s (a: Head, b: Tail) -> Self { Self(South, a, b) }
|
||||
#[inline] pub const fn e (a: Head, b: Tail) -> Self { Self(East, a, b) }
|
||||
#[inline] pub const fn w (a: Head, b: Tail) -> Self { Self(West, a, b) }
|
||||
#[inline] pub const fn a (a: Head, b: Tail) -> Self { Self(Above, a, b) }
|
||||
#[inline] pub const fn b (a: Head, b: Tail) -> Self { Self(Below, a, b) }
|
||||
}
|
||||
|
||||
impl<O: Out, Head: Content<O>, Tail: Content<O>> Draw<O> for Bsp<Head, Tail> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
match self.0 {
|
||||
South => {
|
||||
//panic!("{}", self.1.h(to.area()));
|
||||
let area_1 = self.1.layout(to.area());
|
||||
let area_2 = self.2.layout(XYWH(
|
||||
to.area().x(), to.area().y().plus(area_1.h()),
|
||||
to.area().w(), to.area().h().minus(area_1.h())
|
||||
));
|
||||
//panic!("{area_1:?} {area_2:?}");
|
||||
to.place_at(area_1, &self.1);
|
||||
to.place_at(area_2, &self.2);
|
||||
},
|
||||
_ => todo!("{:?}", self.0)
|
||||
}
|
||||
//let [a, b, _] = bsp_areas(to.area(), self.0, &self.1, &self.2);
|
||||
//panic!("{a:?} {b:?}");
|
||||
//if self.0 == Below {
|
||||
//to.place_at(a, &self.1);
|
||||
//to.place_at(b, &self.2);
|
||||
//} else {
|
||||
//to.place_at(b, &self.2);
|
||||
//to.place_at(a, &self.1);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, Head: Layout<O>, Tail: Layout<O>> Layout<O> for Bsp<Head, Tail> {
|
||||
fn layout_w (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | North | South => self.1.layout_w(area).max(self.2.layout_w(area)),
|
||||
East | West => self.1.layout_w_min(area).plus(self.2.layout_w(area)),
|
||||
}
|
||||
}
|
||||
fn layout_w_min (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | North | South => self.1.layout_w_min(area).max(self.2.layout_w_min(area)),
|
||||
East | West => self.1.layout_w_min(area).plus(self.2.layout_w_min(area)),
|
||||
}
|
||||
}
|
||||
fn layout_w_max (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | North | South => self.1.layout_w_max(area).max(self.2.layout_w_max(area)),
|
||||
East | West => self.1.layout_w_max(area).plus(self.2.layout_w_max(area)),
|
||||
}
|
||||
}
|
||||
fn layout_h (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | East | West => self.1.layout_h(area).max(self.2.layout_h(area)),
|
||||
North | South => self.1.layout_h(area).plus(self.2.layout_h(area)),
|
||||
}
|
||||
}
|
||||
fn layout_h_min (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | East | West => self.1.layout_h_min(area).max(self.2.layout_h_min(area)),
|
||||
North | South => self.1.layout_h_min(area).plus(self.2.layout_h_min(area)),
|
||||
}
|
||||
}
|
||||
fn layout_h_max (&self, area: XYWH<O::Unit>) -> O::Unit {
|
||||
match self.0 {
|
||||
Above | Below | North | South => self.1.layout_h_max(area).max(self.2.layout_h_max(area)),
|
||||
East | West => self.1.layout_h_max(area).plus(self.2.layout_h_max(area)),
|
||||
}
|
||||
}
|
||||
fn layout (&self, area: XYWH<O::Unit>) -> XYWH<O::Unit> {
|
||||
bsp_areas(area, self.0, &self.1, &self.2)[2]
|
||||
}
|
||||
}
|
||||
|
||||
fn bsp_areas <O: Out, A: Layout<O>, B: Layout<O>> (
|
||||
area: XYWH<O::Unit>,
|
||||
direction: Direction,
|
||||
a: &A,
|
||||
b: &B,
|
||||
) -> [XYWH<O::Unit>;3] {
|
||||
let XYWH(x, y, w, h) = area;
|
||||
let WH(aw, ah) = a.layout(area).wh();
|
||||
let WH(bw, bh) = b.layout(match direction {
|
||||
South => XYWH(x, y + ah, w, h.minus(ah)),
|
||||
North => XYWH(x, y, w, h.minus(ah)),
|
||||
East => XYWH(x + aw, y, w.minus(aw), h),
|
||||
West => XYWH(x, y, w.minus(aw), h),
|
||||
Above => area,
|
||||
Below => area,
|
||||
}).wh();
|
||||
match direction {
|
||||
Above | Below => {
|
||||
let XYWH(x, y, w, h) = area.centered_xy([aw.max(bw), ah.max(bh)]);
|
||||
let a = XYWH((x + w/2.into()).minus(aw/2.into()), (y + h/2.into()).minus(ah/2.into()), aw, ah);
|
||||
let b = XYWH((x + w/2.into()).minus(bw/2.into()), (y + h/2.into()).minus(bh/2.into()), bw, bh);
|
||||
[a.into(), b.into(), XYWH(x, y, w, h)]
|
||||
},
|
||||
South => {
|
||||
let XYWH(x, y, w, h) = area.centered_xy([aw.max(bw), ah + bh]);
|
||||
let a = XYWH((x + w/2.into()).minus(aw/2.into()), y, aw, ah);
|
||||
let b = XYWH((x + w/2.into()).minus(bw/2.into()), y + ah, bw, bh);
|
||||
[a.into(), b.into(), XYWH(x, y, w, h)]
|
||||
},
|
||||
North => {
|
||||
let XYWH(x, y, w, h) = area.centered_xy([aw.max(bw), ah + bh]);
|
||||
let a = XYWH((x + (w/2.into())).minus(aw/2.into()), y + bh, aw, ah);
|
||||
let b = XYWH((x + (w/2.into())).minus(bw/2.into()), y, bw, bh);
|
||||
[a.into(), b.into(), XYWH(x, y, w, h)]
|
||||
},
|
||||
East => {
|
||||
let XYWH(x, y, w, h) = area.centered_xy([aw + bw, ah.max(bh)]);
|
||||
let a = XYWH(x, (y + h/2.into()).minus(ah/2.into()), aw, ah);
|
||||
let b = XYWH(x + aw, (y + h/2.into()).minus(bh/2.into()), bw, bh);
|
||||
[a.into(), b.into(), XYWH(x, y, w, h)]
|
||||
},
|
||||
West => {
|
||||
let XYWH(x, y, w, h) = area.centered_xy([aw + bw, ah.max(bh)]);
|
||||
let a = XYWH(x + bw, (y + h/2.into()).minus(ah/2.into()), aw, ah);
|
||||
let b = XYWH(x, (y + h/2.into()).minus(bh/2.into()), bw, bh);
|
||||
[a.into(), b.into(), XYWH(x, y, w, h)]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, O, A, B, I, F, G> Map<O, A, B, I, F, G> where
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
{
|
||||
pub const fn new (get_iter: F, get_item: G) -> Self {
|
||||
Self {
|
||||
__: PhantomData,
|
||||
get_iter,
|
||||
get_item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_map_direction!(east, X, w);
|
||||
impl_map_direction!(south, Y, n);
|
||||
impl_map_direction!(west, X, e);
|
||||
impl_map_direction!(north, Y, s);
|
||||
|
||||
impl<'a, O, A, B, I, F, G> Layout<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Layout<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
{
|
||||
fn layout (&self, area: XYWH<O::Unit>) -> XYWH<O::Unit> {
|
||||
let Self { get_iter, get_item, .. } = self;
|
||||
let mut index = 0;
|
||||
let XY(mut min_x, mut min_y) = area.centered();
|
||||
let XY(mut max_x, mut max_y) = area.center();
|
||||
for item in get_iter() {
|
||||
let XYWH(x, y, w, h) = get_item(item, index).layout(area);
|
||||
min_x = min_x.min(x);
|
||||
min_y = min_y.min(y);
|
||||
max_x = max_x.max(x + w);
|
||||
max_y = max_y.max(y + h);
|
||||
index += 1;
|
||||
}
|
||||
let w = max_x - min_x;
|
||||
let h = max_y - min_y;
|
||||
//[min_x.into(), min_y.into(), w.into(), h.into()].into()
|
||||
area.centered_xy([w.into(), h.into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, O, A, B, I, F, G> Draw<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Content<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
{
|
||||
fn draw (&self, to: &mut O) {
|
||||
let Self { get_iter, get_item, .. } = self;
|
||||
let mut index = 0;
|
||||
let area = self.layout(to.area());
|
||||
for item in get_iter() {
|
||||
let item = get_item(item, index);
|
||||
//to.place_at(area.into(), &item);
|
||||
to.place_at(item.layout(area), &item);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline] pub fn map_south<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_height: O::Unit,
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::Y(item_offset, Fixed::Y(item_height, Fill::X(item)))
|
||||
}
|
||||
|
||||
#[inline] pub fn map_south_west<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_height: O::Unit,
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::Y(item_offset, Align::nw(Fixed::Y(item_height, Fill::X(item))))
|
||||
}
|
||||
|
||||
#[inline] pub fn map_east<O: Out>(
|
||||
item_offset: O::Unit,
|
||||
item_width: O::Unit,
|
||||
item: impl Content<O>
|
||||
) -> impl Content<O> {
|
||||
Push::X(item_offset, Align::w(Fixed::X(item_width, Fill::Y(item))))
|
||||
}
|
||||
|
||||
impl Tryptich<(), (), ()> {
|
||||
pub fn center (h: u16) -> Self {
|
||||
Self { h, top: false, left: (0, ()), middle: (0, ()), right: (0, ()) }
|
||||
}
|
||||
pub fn top (h: u16) -> Self {
|
||||
Self { h, top: true, left: (0, ()), middle: (0, ()), right: (0, ()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, C> Tryptich<A, B, C> {
|
||||
pub fn left <D> (self, w: u16, content: D) -> Tryptich<D, B, C> {
|
||||
Tryptich { left: (w, content), ..self }
|
||||
}
|
||||
pub fn middle <D> (self, w: u16, content: D) -> Tryptich<A, D, C> {
|
||||
Tryptich { middle: (w, content), ..self }
|
||||
}
|
||||
pub fn right <D> (self, w: u16, content: D) -> Tryptich<A, B, D> {
|
||||
Tryptich { right: (w, content), ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, Color, Item: Layout<O>> Layout<O> for Foreground<Color, Item> {
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> { self.1.layout(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, Color, Item: Layout<O>> Layout<O> for Background<Color, Item> {
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> { self.1.layout(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> HasContent<O> for FieldH<T, L, V> {
|
||||
fn content (&self) -> impl Content<O> { Bsp::e(&self.1, &self.2) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> Layout<O> for FieldH<T, L, V> {
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> { self.content().layout(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> Draw<O> for FieldH<T, L, V> {
|
||||
fn draw (&self, to: &mut O) { self.content().draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> HasContent<O> for FieldV<T, L, V> {
|
||||
fn content (&self) -> impl Content<O> { Bsp::s(&self.1, &self.2) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> Layout<O> for FieldV<T, L, V> {
|
||||
fn layout (&self, to: XYWH<O::Unit>) -> XYWH<O::Unit> { self.content().layout(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T, L: Content<O>, V: Content<O>> Draw<O> for FieldV<T, L, V> {
|
||||
fn draw (&self, to: &mut O) { self.content().draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, S: Layout<O>> Layout<O> for Border<S> {
|
||||
fn layout (&self, area: XYWH<O::Unit>) -> XYWH<O::Unit> {
|
||||
self.1.layout(area)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, T, U> Field<C, T, U> {
|
||||
pub fn new (direction: Direction) -> Field<C, (), ()> {
|
||||
Field::<C, (), ()> {
|
||||
direction,
|
||||
label: None, label_fg: None, label_bg: None, label_align: None,
|
||||
value: None, value_fg: None, value_bg: None, value_align: None,
|
||||
}
|
||||
}
|
||||
pub fn label <L> (
|
||||
self, label: Option<L>, align: Option<Direction>, fg: Option<C>, bg: Option<C>
|
||||
) -> Field<C, L, U> {
|
||||
Field::<C, L, U> { label, label_fg: fg, label_bg: bg, label_align: align, ..self }
|
||||
}
|
||||
pub fn value <V> (
|
||||
self, value: Option<V>, align: Option<Direction>, fg: Option<C>, bg: Option<C>
|
||||
) -> Field<C, T, V> {
|
||||
Field::<C, T, V> { value, value_fg: fg, value_bg: bg, value_align: align, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PerfModel {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
enabled: true,
|
||||
clock: quanta::Clock::new(),
|
||||
used: Default::default(),
|
||||
window: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PerfModel {
|
||||
pub fn get_t0 (&self) -> Option<u64> {
|
||||
if self.enabled {
|
||||
Some(self.clock.raw())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn get_t1 (&self, t0: Option<u64>) -> Option<std::time::Duration> {
|
||||
if let Some(t0) = t0 {
|
||||
if self.enabled {
|
||||
Some(self.clock.delta(t0, self.clock.raw()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn update (&self, t0: Option<u64>, microseconds: f64) {
|
||||
if let Some(t0) = t0 {
|
||||
let t1 = self.clock.raw();
|
||||
self.used.store(self.clock.delta_as_nanos(t0, t1) as f64, Relaxed);
|
||||
self.window.store(microseconds, Relaxed,);
|
||||
}
|
||||
}
|
||||
pub fn percentage (&self) -> Option<f64> {
|
||||
let window = self.window.load(Relaxed) * 1000.0;
|
||||
if window > 0.0 {
|
||||
let used = self.used.load(Relaxed);
|
||||
Some(100.0 * used / window)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue