Track retained layout validity explicitly

This commit is contained in:
iris-ai committed 2026-09-15 16:03:53 -04:00
1 parent 691e3eb23c
commit 29c7881c8a
25 files changed
+836 -795

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
use crate::UiScalar;
use std::ops::RangeInclusive;
/// The lengths of a box, in pixels, that one drawing of a widget holds for:
/// give the widget any box in this range and it draws the same thing and
/// reports the same size. A widget that never reads its box in pixels holds
/// for every length; one that does holds for the one it read unless it says
/// otherwise, and a parent holds for whatever keeps every child it asked
/// about or drew inside its own range.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Holds {
pub lo: f32,
pub hi: f32,
}
/// How far outside a range a length may fall and still be inside it: a box
/// offered back to a widget at the length it reported comes back through the
/// chain a few bits off, and nothing a reader could see lives in that gap.
pub const HOLDS_EPSILON_PX: f32 = 0.05;
impl Holds {
pub const ANY: Self = Self {
lo: f32::NEG_INFINITY,
hi: f32::INFINITY,
};
pub const fn at(len: f32) -> Self {
Self { lo: len, hi: len }
}
pub fn contains(&self, len: f32) -> bool {
len >= self.lo - HOLDS_EPSILON_PX && len <= self.hi + HOLDS_EPSILON_PX
}
pub fn and(self, other: Self) -> Self {
Self {
lo: self.lo.max(other.lo),
hi: self.hi.min(other.hi),
}
}
/// What a box has to be for a part of it, `len` of the box long, to stay
/// in this range. A part with no relative extent is a fixed length: it
/// was drawn at that length and any box keeps it there.
pub fn through(self, len: UiScalar) -> Self {
if len.rel == 0.0 {
return Self::ANY;
}
let a = (self.lo - len.px) / len.rel;
let b = (self.hi - len.px) / len.rel;
Self {
lo: a.min(b),
hi: a.max(b),
}
}
}
impl From<RangeInclusive<f32>> for Holds {
fn from(range: RangeInclusive<f32>) -> Self {
Self {
lo: *range.start(),
hi: *range.end(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn through_reverses_a_range_for_a_negative_fraction() {
assert_eq!(
Holds { lo: 20.0, hi: 40.0 }.through(UiScalar::new(-0.5, 10.0)),
Holds {
lo: -60.0,
hi: -20.0
}
);
}
}