Track retained layout validity explicitly
This commit is contained in:
1 parent
691e3eb23c
commit
29c7881c8a
25 files changed
+836
-795
No files matched your search
@@ -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
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user