Give a length with no share in it its own type again
`UiScalar` was `Len` without the `leftover` weight, which is the separation canonical `main` already had as `Len` beside `LayoutLen` and this branch collapsed. It is needed back for the queued clamp: a cap may not contain a share, because a cap has to read the report a rule otherwise makes moot, and a share puts the container's division into the same equation -- two self-consistent assignments, which is the multiple-fixed-point failure generated seed 13 punished for orthogonal sizing. `min(report, cap)` is not a `LayoutLen` either: it is a sum of parts, and the smaller of two of them is not one. So `UiScalar` is `Len`, what was `Len` is `LayoutLen`, and the two say in their docs which is which: a `Len` is pixels plus a fraction of a box -- a position being the length from the box's start, which is why a span is two of them -- and a `LayoutLen` is a `Len` plus a claim only a container dividing its room can answer. `From<Len> for LayoutLen` is the one-way step between them. Names only; the shader's `UiScalar` is renamed with them. Checked: fmt, clippy, 105 tests, and `tabs`, `minimal`, `view`, `text` and `random` byte-identical at 1920x1200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f5e27cba9
commit
a8898aaa54
27 files changed
+218
-202
No files matched your search
@@ -15,7 +15,7 @@
|
|||||||
//! reuse, size, placement, and text events for one suspicious widget. The
|
//! reuse, size, placement, and text events for one suspicious widget. The
|
||||||
//! selection is a set and survives [`take`] until cleared.
|
//! selection is a set and survives [`take`] until cleared.
|
||||||
|
|
||||||
use crate::{Axis, Len, PxVec2, Size, UiRegion, WidgetId};
|
use crate::{Axis, LayoutLen, PxVec2, Size, UiRegion, WidgetId};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
@@ -287,7 +287,7 @@ pub enum TraceEvent {
|
|||||||
id: WidgetId,
|
id: WidgetId,
|
||||||
reader: WidgetId,
|
reader: WidgetId,
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
hint: Option<Len>,
|
hint: Option<LayoutLen>,
|
||||||
},
|
},
|
||||||
TextRendered {
|
TextRendered {
|
||||||
id: WidgetId,
|
id: WidgetId,
|
||||||
@@ -389,7 +389,7 @@ pub(crate) fn size_read(id: WidgetId, reader: WidgetId, size: Size) {
|
|||||||
trace(id, TraceEvent::SizeRead { id, reader, size });
|
trace(id, TraceEvent::SizeRead { id, reader, size });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn hint_read(id: WidgetId, reader: WidgetId, axis: Axis, hint: Option<Len>) {
|
pub(crate) fn hint_read(id: WidgetId, reader: WidgetId, axis: Axis, hint: Option<LayoutLen>) {
|
||||||
trace(
|
trace(
|
||||||
id,
|
id,
|
||||||
TraceEvent::HintRead {
|
TraceEvent::HintRead {
|
||||||
|
|||||||
@@ -172,14 +172,14 @@ impl Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiScalar {
|
impl Len {
|
||||||
pub const fn align(&self, align: AxisAlign) -> UiSpan {
|
pub const fn align(&self, align: AxisAlign) -> UiSpan {
|
||||||
let rel = align.rel();
|
let rel = align.rel();
|
||||||
let rest = Rel::ONE.sub(rel);
|
let rest = Rel::ONE.sub(rel);
|
||||||
let at = UiScalar::from_parts(rel, Px::ZERO);
|
let at = Len::from_parts(rel, Px::ZERO);
|
||||||
UiSpan {
|
UiSpan {
|
||||||
start: UiScalar::from_parts(at.rel.sub(self.rel.mul(rel)), at.px.sub(self.px.mul(rel))),
|
start: Len::from_parts(at.rel.sub(self.rel.mul(rel)), at.px.sub(self.px.mul(rel))),
|
||||||
end: UiScalar::from_parts(at.rel.add(self.rel.mul(rest)), at.px.add(self.px.mul(rest))),
|
end: Len::from_parts(at.rel.add(self.rel.mul(rest)), at.px.add(self.px.mul(rest))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,8 +221,8 @@ impl From<CardinalAlign> for Align {
|
|||||||
const impl From<RegionAlign> for UiVec2 {
|
const impl From<RegionAlign> for UiVec2 {
|
||||||
fn from(align: RegionAlign) -> Self {
|
fn from(align: RegionAlign) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
UiScalar::from_parts(align.x.rel(), Px::ZERO),
|
Len::from_parts(align.x.rel(), Px::ZERO),
|
||||||
UiScalar::from_parts(align.y.rel(), Px::ZERO),
|
Len::from_parts(align.y.rel(), Px::ZERO),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-37
@@ -3,23 +3,28 @@ use crate::{Px, PxVec2, Rel, UiNum, Weight, util::impl_op};
|
|||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||||
pub struct Size {
|
pub struct Size {
|
||||||
pub x: Len,
|
pub x: LayoutLen,
|
||||||
pub y: Len,
|
pub y: LayoutLen,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What a widget asks for along one axis: pixels, a fraction of the box it
|
/// What a widget asks for along one axis: a [`Len`] -- pixels and a fraction
|
||||||
/// is given, and a share of whatever is left over once everything fixed has
|
/// of the box it is given -- plus a share of whatever is left over once
|
||||||
/// been taken. The three add up rather than choosing between one another.
|
/// everything fixed has been taken. The parts add up rather than choosing
|
||||||
|
/// between one another.
|
||||||
|
///
|
||||||
|
/// Only a container dividing its room can answer a share, so a length nobody
|
||||||
|
/// divides is a `Len`: a position, a padding, a cap, anything already
|
||||||
|
/// resolved.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Len {
|
pub struct LayoutLen {
|
||||||
pub px: Px,
|
pub px: Px,
|
||||||
pub rel: Rel,
|
pub rel: Rel,
|
||||||
pub leftover: Weight,
|
pub leftover: Weight,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: UiNum> From<N> for Len {
|
impl<N: UiNum> From<N> for LayoutLen {
|
||||||
fn from(value: N) -> Self {
|
fn from(value: N) -> Self {
|
||||||
Len::px(value.to_f32())
|
LayoutLen::px(value.to_f32())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,21 +37,33 @@ impl<Nx: UiNum, Ny: UiNum> From<(Nx, Ny)> for Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Len> for Size {
|
/// A length with no share in it is a length a container does not have to
|
||||||
fn from(value: Len) -> Self {
|
/// divide, which is one it can always give.
|
||||||
|
impl From<Len> for LayoutLen {
|
||||||
|
fn from(len: Len) -> Self {
|
||||||
|
Self {
|
||||||
|
px: len.px,
|
||||||
|
rel: len.rel,
|
||||||
|
leftover: Weight::ZERO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LayoutLen> for Size {
|
||||||
|
fn from(value: LayoutLen) -> Self {
|
||||||
Self { x: value, y: value }
|
Self { x: value, y: value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Size {
|
impl Size {
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
x: Len::ZERO,
|
x: LayoutLen::ZERO,
|
||||||
y: Len::ZERO,
|
y: LayoutLen::ZERO,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LEFTOVER: Self = Self {
|
pub const LEFTOVER: Self = Self {
|
||||||
x: Len::LEFTOVER,
|
x: LayoutLen::LEFTOVER,
|
||||||
y: Len::LEFTOVER,
|
y: LayoutLen::LEFTOVER,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// From something measured outside layout -- a texture, a shaped line --
|
/// From something measured outside layout -- a texture, a shaped line --
|
||||||
@@ -57,28 +74,28 @@ impl Size {
|
|||||||
|
|
||||||
pub const fn from_px(v: PxVec2) -> Self {
|
pub const fn from_px(v: PxVec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x: Len {
|
x: LayoutLen {
|
||||||
px: v.x,
|
px: v.x,
|
||||||
..Len::ZERO
|
..LayoutLen::ZERO
|
||||||
},
|
},
|
||||||
y: Len {
|
y: LayoutLen {
|
||||||
px: v.y,
|
px: v.y,
|
||||||
..Len::ZERO
|
..LayoutLen::ZERO
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rel(v: Vec2) -> Self {
|
pub fn rel(v: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x: Len::rel(v.x),
|
x: LayoutLen::rel(v.x),
|
||||||
y: Len::rel(v.y),
|
y: LayoutLen::rel(v.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leftover(v: Vec2) -> Self {
|
pub fn leftover(v: Vec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x: Len::leftover(v.x),
|
x: LayoutLen::leftover(v.x),
|
||||||
y: Len::leftover(v.y),
|
y: LayoutLen::leftover(v.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +106,7 @@ impl Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_axis(axis: Axis, aligned: Len, ortho: Len) -> Self {
|
pub fn from_axis(axis: Axis, aligned: LayoutLen, ortho: LayoutLen) -> Self {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::X => Self {
|
Axis::X => Self {
|
||||||
x: aligned,
|
x: aligned,
|
||||||
@@ -102,7 +119,7 @@ impl Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn axis(&self, axis: Axis) -> Len {
|
pub fn axis(&self, axis: Axis) -> LayoutLen {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::X => self.x,
|
Axis::X => self.x,
|
||||||
Axis::Y => self.y,
|
Axis::Y => self.y,
|
||||||
@@ -110,7 +127,7 @@ impl Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Len {
|
impl LayoutLen {
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
px: Px::ZERO,
|
px: Px::ZERO,
|
||||||
rel: Rel::ZERO,
|
rel: Rel::ZERO,
|
||||||
@@ -126,12 +143,12 @@ impl Len {
|
|||||||
/// The whole of what is left over counts as the whole box, which is what
|
/// The whole of what is left over counts as the whole box, which is what
|
||||||
/// a length means to something that is not dividing a box between
|
/// a length means to something that is not dividing a box between
|
||||||
/// siblings -- a scroll asking how long its content is.
|
/// siblings -- a scroll asking how long its content is.
|
||||||
pub fn apply_leftover(&self) -> UiScalar {
|
pub fn apply_leftover(&self) -> Len {
|
||||||
let share = match self.leftover > Weight::ZERO {
|
let share = match self.leftover > Weight::ZERO {
|
||||||
true => Rel::ONE,
|
true => Rel::ONE,
|
||||||
false => Rel::ZERO,
|
false => Rel::ZERO,
|
||||||
};
|
};
|
||||||
UiScalar::from_parts(self.rel.add(share), self.px)
|
Len::from_parts(self.rel.add(share), self.px)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn px(px: impl UiNum) -> Self {
|
pub fn px(px: impl UiNum) -> Self {
|
||||||
@@ -157,24 +174,24 @@ impl Len {
|
|||||||
pub mod len_fns {
|
pub mod len_fns {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn px(px: impl UiNum) -> Len {
|
pub fn px(px: impl UiNum) -> LayoutLen {
|
||||||
Len::px(px)
|
LayoutLen::px(px)
|
||||||
}
|
}
|
||||||
pub fn rel(rel: impl UiNum) -> Len {
|
pub fn rel(rel: impl UiNum) -> LayoutLen {
|
||||||
Len::rel(rel)
|
LayoutLen::rel(rel)
|
||||||
}
|
}
|
||||||
pub fn leftover(ratio: impl UiNum) -> Len {
|
pub fn leftover(ratio: impl UiNum) -> LayoutLen {
|
||||||
Len::leftover(ratio)
|
LayoutLen::leftover(ratio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_op!(same Len Add add; px rel leftover);
|
impl_op!(same LayoutLen Add add; px rel leftover);
|
||||||
impl_op!(same Len Sub sub; px rel leftover);
|
impl_op!(same LayoutLen Sub sub; px rel leftover);
|
||||||
|
|
||||||
impl_op!(same Size Add add; x y);
|
impl_op!(same Size Add add; x y);
|
||||||
impl_op!(same Size Sub sub; x y);
|
impl_op!(same Size Sub sub; x y);
|
||||||
|
|
||||||
impl Default for Len {
|
impl Default for LayoutLen {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::leftover(1.0)
|
Self::leftover(1.0)
|
||||||
}
|
}
|
||||||
@@ -186,7 +203,7 @@ impl std::fmt::Display for Size {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Len {
|
impl std::fmt::Display for LayoutLen {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if self.px != Px::ZERO {
|
if self.px != Px::ZERO {
|
||||||
write!(f, "{} px;", self.px)?;
|
write!(f, "{} px;", self.px)?;
|
||||||
|
|||||||
+42
-38
@@ -6,41 +6,41 @@ use crate::{Px, PxVec2, Rel, UiNum, util::impl_op};
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, bytemuck::Zeroable, Default)]
|
||||||
pub struct UiVec2 {
|
pub struct UiVec2 {
|
||||||
pub x: UiScalar,
|
pub x: Len,
|
||||||
pub y: UiScalar,
|
pub y: Len,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiVec2 {
|
impl UiVec2 {
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
x: UiScalar::ZERO,
|
x: Len::ZERO,
|
||||||
y: UiScalar::ZERO,
|
y: Len::ZERO,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const fn new(x: UiScalar, y: UiScalar) -> Self {
|
pub const fn new(x: Len, y: Len) -> Self {
|
||||||
Self { x, y }
|
Self { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn px(px: impl const Into<Vec2>) -> Self {
|
pub const fn px(px: impl const Into<Vec2>) -> Self {
|
||||||
let px = px.into();
|
let px = px.into();
|
||||||
Self {
|
Self {
|
||||||
x: UiScalar::px(px.x),
|
x: Len::px(px.x),
|
||||||
y: UiScalar::px(px.y),
|
y: Len::px(px.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// From lengths already on the grid, with no fraction of a box.
|
/// From lengths already on the grid, with no fraction of a box.
|
||||||
pub const fn from_px(px: PxVec2) -> Self {
|
pub const fn from_px(px: PxVec2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x: UiScalar::from_parts(Rel::ZERO, px.x),
|
x: Len::from_parts(Rel::ZERO, px.x),
|
||||||
y: UiScalar::from_parts(Rel::ZERO, px.y),
|
y: Len::from_parts(Rel::ZERO, px.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn rel(rel: impl const Into<Vec2>) -> Self {
|
pub const fn rel(rel: impl const Into<Vec2>) -> Self {
|
||||||
let rel = rel.into();
|
let rel = rel.into();
|
||||||
Self {
|
Self {
|
||||||
x: UiScalar::rel(rel.x),
|
x: Len::rel(rel.x),
|
||||||
y: UiScalar::rel(rel.y),
|
y: Len::rel(rel.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,14 +61,14 @@ impl UiVec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn axis_mut(&mut self, axis: Axis) -> &mut UiScalar {
|
pub fn axis_mut(&mut self, axis: Axis) -> &mut Len {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::X => &mut self.x,
|
Axis::X => &mut self.x,
|
||||||
Axis::Y => &mut self.y,
|
Axis::Y => &mut self.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn axis(&self, axis: Axis) -> UiScalar {
|
pub fn axis(&self, axis: Axis) -> Len {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::X => self.x,
|
Axis::X => self.x,
|
||||||
Axis::Y => self.y,
|
Axis::Y => self.y,
|
||||||
@@ -83,7 +83,7 @@ impl UiVec2 {
|
|||||||
|
|
||||||
pub const FULL_SIZE: Self = Self::rel(Vec2::ONE);
|
pub const FULL_SIZE: Self = Self::rel(Vec2::ONE);
|
||||||
|
|
||||||
pub const fn from_axis(axis: Axis, aligned: UiScalar, ortho: UiScalar) -> Self {
|
pub const fn from_axis(axis: Axis, aligned: Len, ortho: Len) -> Self {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::X => Self {
|
Axis::X => Self {
|
||||||
x: aligned,
|
x: aligned,
|
||||||
@@ -129,21 +129,27 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A position along one axis, as a fraction of the box it sits in plus an
|
/// A length along one axis: a fraction of the box it is measured in plus an
|
||||||
/// offset: `rel * len + px`. Both parts are fixed point, so composing one
|
/// offset, `rel * box + px`. A position is the same number -- the length from
|
||||||
/// through a chain of boxes rounds only where it multiplies and lands on the
|
/// the start of the box to the point -- which is why a [`UiSpan`] is two of
|
||||||
/// same number as any other route to the same place.
|
/// these. Both parts are fixed point, so composing one through a chain of
|
||||||
|
/// boxes rounds only where it multiplies, and lands on the same number as any
|
||||||
|
/// other route to the same place.
|
||||||
|
///
|
||||||
|
/// It carries no claim on what a container has left over. That is
|
||||||
|
/// [`crate::LayoutLen`], which is this plus a weight, and which means nothing
|
||||||
|
/// to anyone but whoever divides the room.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, Default, bytemuck::Zeroable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, bytemuck::Pod, Default, bytemuck::Zeroable)]
|
||||||
pub struct UiScalar {
|
pub struct Len {
|
||||||
pub rel: Rel,
|
pub rel: Rel,
|
||||||
pub px: Px,
|
pub px: Px,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_op!(same UiScalar Add add; rel px);
|
impl_op!(same Len Add add; rel px);
|
||||||
impl_op!(same UiScalar Sub sub; rel px);
|
impl_op!(same Len Sub sub; rel px);
|
||||||
|
|
||||||
impl UiScalar {
|
impl Len {
|
||||||
pub const ZERO: Self = Self {
|
pub const ZERO: Self = Self {
|
||||||
rel: Rel::ZERO,
|
rel: Rel::ZERO,
|
||||||
px: Px::ZERO,
|
px: Px::ZERO,
|
||||||
@@ -192,10 +198,8 @@ impl UiScalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Both channels by the same factor, which is what a fraction of a
|
/// Both parts by the same fraction, which is what a part of a length
|
||||||
/// length means when the length is part pixels and part a share.
|
/// means when the length is part pixels and part a fraction of a box.
|
||||||
/// Both channels by the same fraction, which is what a part of a length
|
|
||||||
/// means when the length is part pixels and part a share.
|
|
||||||
pub const fn scale(&self, by: Rel) -> Self {
|
pub const fn scale(&self, by: Rel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rel: self.rel.mul(by),
|
rel: self.rel.mul(by),
|
||||||
@@ -215,14 +219,14 @@ impl UiScalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn within_len(&self, len: UiScalar) -> Self {
|
pub fn within_len(&self, len: Len) -> Self {
|
||||||
self.within(&UiSpan {
|
self.within(&UiSpan {
|
||||||
start: UiScalar::ZERO,
|
start: Len::ZERO,
|
||||||
end: len,
|
end: len,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_len(&self, len: UiScalar) -> Self {
|
pub fn select_len(&self, len: Len) -> Self {
|
||||||
len.within_len(*self)
|
len.within_len(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,24 +249,24 @@ impl UiScalar {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Debug, Copy, Clone, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
pub struct UiSpan {
|
pub struct UiSpan {
|
||||||
pub start: UiScalar,
|
pub start: Len,
|
||||||
pub end: UiScalar,
|
pub end: Len,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiSpan {
|
impl UiSpan {
|
||||||
pub const FULL: Self = Self {
|
pub const FULL: Self = Self {
|
||||||
start: UiScalar::ZERO,
|
start: Len::ZERO,
|
||||||
end: UiScalar::FULL,
|
end: Len::FULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const fn rel(rel: f32) -> Self {
|
pub const fn rel(rel: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
start: UiScalar::rel(rel),
|
start: Len::rel(rel),
|
||||||
end: UiScalar::rel(rel),
|
end: Len::rel(rel),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn new(start: UiScalar, end: UiScalar) -> Self {
|
pub const fn new(start: Len, end: Len) -> Self {
|
||||||
Self { start, end }
|
Self { start, end }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +277,7 @@ impl UiSpan {
|
|||||||
std::mem::swap(&mut self.start.px, &mut self.end.px);
|
std::mem::swap(&mut self.start.px, &mut self.end.px);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn shift(&mut self, offset: UiScalar) {
|
pub const fn shift(&mut self, offset: Len) {
|
||||||
self.start += offset;
|
self.start += offset;
|
||||||
self.end += offset;
|
self.end += offset;
|
||||||
}
|
}
|
||||||
@@ -285,7 +289,7 @@ impl UiSpan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn len(&self) -> UiScalar {
|
pub const fn len(&self) -> Len {
|
||||||
self.end - self.start
|
self.end - self.start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ struct RawSpan {
|
|||||||
end: RawScalar,
|
end: RawScalar,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_of(raw: RawScalar) -> UiScalar {
|
fn scalar_of(raw: RawScalar) -> Len {
|
||||||
return UiScalar(f32(raw.rel) * REL_STEP, f32(raw.px) * PX_STEP);
|
return Len(f32(raw.rel) * REL_STEP, f32(raw.px) * PX_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn span_of(raw: RawSpan) -> UiSpan {
|
fn span_of(raw: RawSpan) -> UiSpan {
|
||||||
return UiSpan(scalar_of(raw.start), scalar_of(raw.end));
|
return UiSpan(scalar_of(raw.start), scalar_of(raw.end));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_of_pair(raw: vec2<i32>) -> UiScalar {
|
fn scalar_of_pair(raw: vec2<i32>) -> Len {
|
||||||
return UiScalar(f32(raw.x) * REL_STEP, f32(raw.y) * PX_STEP);
|
return Len(f32(raw.x) * REL_STEP, f32(raw.y) * PX_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Region {
|
struct Region {
|
||||||
@@ -72,12 +72,12 @@ const MOVE_NONE: u32 = 4294967295u;
|
|||||||
// resolve a deep one the same way.
|
// resolve a deep one the same way.
|
||||||
const CHAIN_LIMIT: u32 = 64u;
|
const CHAIN_LIMIT: u32 = 64u;
|
||||||
|
|
||||||
// The same expression `UiScalar::within` uses, in floats rather than on the
|
// The same expression `Len::within` uses, in floats rather than on the
|
||||||
// CPU's grid: a move is resolved here so that scrolling a subtree writes one
|
// CPU's grid: a move is resolved here so that scrolling a subtree writes one
|
||||||
// entry instead of walking it. What has to hold is that this agrees with
|
// entry instead of walking it. What has to hold is that this agrees with
|
||||||
// itself frame to frame, not that it matches the CPU to the last bit.
|
// itself frame to frame, not that it matches the CPU to the last bit.
|
||||||
fn scalar_within(s: UiScalar, p: UiSpan) -> UiScalar {
|
fn scalar_within(s: Len, p: UiSpan) -> Len {
|
||||||
return UiScalar(
|
return Len(
|
||||||
p.start.rel + (p.end.rel - p.start.rel) * s.rel,
|
p.start.rel + (p.end.rel - p.start.rel) * s.rel,
|
||||||
s.px + (p.start.px + (p.end.px - p.start.px) * s.rel),
|
s.px + (p.start.px + (p.end.px - p.start.px) * s.rel),
|
||||||
);
|
);
|
||||||
@@ -102,11 +102,11 @@ fn resolve_move(idx: u32, local: Region) -> Region {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct UiSpan {
|
struct UiSpan {
|
||||||
start: UiScalar,
|
start: Len,
|
||||||
end: UiScalar,
|
end: Len,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UiScalar {
|
struct Len {
|
||||||
rel: f32,
|
rel: f32,
|
||||||
px: f32,
|
px: f32,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
Holds, LayerId, Len, MaskIdx, MoveIdx, PrimitiveHandle, RegionAlign, Size, TextureHandle,
|
Holds, LayerId, LayoutLen, MaskIdx, MoveIdx, PrimitiveHandle, RegionAlign, Size, TextureHandle,
|
||||||
UiRegion, WidgetId,
|
UiRegion, WidgetId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ pub struct ActiveData {
|
|||||||
/// The declared lengths whoever drew this widget resolved into its box.
|
/// The declared lengths whoever drew this widget resolved into its box.
|
||||||
/// A change to one moves a box this widget cannot fix by drawing again,
|
/// A change to one moves a box this widget cannot fix by drawing again,
|
||||||
/// and comparing them is what says so.
|
/// and comparing them is what says so.
|
||||||
pub declared: [Option<Len>; 2],
|
pub declared: [Option<LayoutLen>; 2],
|
||||||
/// The alignment its parent asked it with. A local redraw repeats that
|
/// The alignment its parent asked it with. A local redraw repeats that
|
||||||
/// question, including an override chosen by a container.
|
/// question, including an override chosen by a container.
|
||||||
pub align: RegionAlign,
|
pub align: RegionAlign,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Px, REL_SHIFT, UiScalar, fixed::div_toward, fixed::narrow};
|
use crate::{Len, Px, REL_SHIFT, fixed::div_toward, fixed::narrow};
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
/// The lengths of a box, in pixels, that one drawing of a widget holds for:
|
/// The lengths of a box, in pixels, that one drawing of a widget holds for:
|
||||||
@@ -50,7 +50,7 @@ impl Holds {
|
|||||||
/// the length alone instead gives a point that need not even contain the
|
/// the length alone instead gives a point that need not even contain the
|
||||||
/// box the part was drawn in, which is a range excluding the drawing it
|
/// box the part was drawn in, which is a range excluding the drawing it
|
||||||
/// was made for.
|
/// was made for.
|
||||||
pub const fn through(self, len: UiScalar) -> Self {
|
pub const fn through(self, len: Len) -> Self {
|
||||||
let rel = len.rel.raw() as i64;
|
let rel = len.rel.raw() as i64;
|
||||||
if rel == 0 {
|
if rel == 0 {
|
||||||
return Self::ANY;
|
return Self::ANY;
|
||||||
@@ -98,7 +98,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn through_reverses_a_range_for_a_negative_fraction() {
|
fn through_reverses_a_range_for_a_negative_fraction() {
|
||||||
// `10 - box / 2` is between 20 and 40 for boxes from -60 to -20.
|
// `10 - box / 2` is between 20 and 40 for boxes from -60 to -20.
|
||||||
let part = UiScalar::from_parts(Rel::from_f32(-0.5), Px::from_int(10));
|
let part = Len::from_parts(Rel::from_f32(-0.5), Px::from_int(10));
|
||||||
let holds = Holds::from(Px::from_int(20)..=Px::from_int(40)).through(part);
|
let holds = Holds::from(Px::from_int(20)..=Px::from_int(40)).through(part);
|
||||||
assert!(holds.contains(Px::from_int(-60)) && holds.contains(Px::from_int(-20)));
|
assert!(holds.contains(Px::from_int(-60)) && holds.contains(Px::from_int(-20)));
|
||||||
assert!(!holds.contains(Px::from_int(-61)) && !holds.contains(Px::from_int(-19)));
|
assert!(!holds.contains(Px::from_int(-61)) && !holds.contains(Px::from_int(-19)));
|
||||||
@@ -109,7 +109,7 @@ mod tests {
|
|||||||
/// box is not a whole number of steps.
|
/// box is not a whole number of steps.
|
||||||
#[test]
|
#[test]
|
||||||
fn a_part_maps_back_onto_the_box_it_was_measured_in() {
|
fn a_part_maps_back_onto_the_box_it_was_measured_in() {
|
||||||
let part = UiScalar::from_parts(Rel::from_f32(1.0 / 3.0), Px::from_int(-146));
|
let part = Len::from_parts(Rel::from_f32(1.0 / 3.0), Px::from_int(-146));
|
||||||
for box_len in (440..460).map(Px::from_int) {
|
for box_len in (440..460).map(Px::from_int) {
|
||||||
let holds = Holds::at(part.to_px(box_len)).through(part);
|
let holds = Holds::at(part.to_px(box_len)).through(part);
|
||||||
assert!(holds.contains(box_len), "{box_len:?} left out by {holds:?}");
|
assert!(holds.contains(box_len), "{box_len:?} left out by {holds:?}");
|
||||||
|
|||||||
+11
-11
@@ -1,8 +1,8 @@
|
|||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
use crate::layout_diagnostics::{self as diag, Counter};
|
use crate::layout_diagnostics::{self as diag, Counter};
|
||||||
use crate::{
|
use crate::{
|
||||||
Axis, Holds, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget, TextAttrs,
|
Axis, Holds, LayoutLen, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget,
|
||||||
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, Weight,
|
TextAttrs, TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiVec2, Weight,
|
||||||
WidgetId, Widgets,
|
WidgetId, Widgets,
|
||||||
render::{
|
render::{
|
||||||
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveHandle, PrimitiveInst,
|
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveHandle, PrimitiveInst,
|
||||||
@@ -109,7 +109,7 @@ impl<'a> Painter<'a> {
|
|||||||
/// it resolves into its box. Reading them depends on nothing -- the box
|
/// it resolves into its box. Reading them depends on nothing -- the box
|
||||||
/// that comes of them is kept on the child, and `redraw` compares it
|
/// that comes of them is kept on the child, and `redraw` compares it
|
||||||
/// there.
|
/// there.
|
||||||
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<Len>; 2] {
|
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<LayoutLen>; 2] {
|
||||||
declared_lens(self.rsc.widgets(), id.id())
|
declared_lens(self.rsc.widgets(), id.id())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ impl<'a> Painter<'a> {
|
|||||||
|
|
||||||
/// What a child says its length is without being drawn, if it can say.
|
/// What a child says its length is without being drawn, if it can say.
|
||||||
/// Asking counts as reading its size.
|
/// Asking counts as reading its size.
|
||||||
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<Len> {
|
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<LayoutLen> {
|
||||||
let widgets = self.rsc.widgets();
|
let widgets = self.rsc.widgets();
|
||||||
// A rule is the answer where there is one: it wins over whatever the
|
// A rule is the answer where there is one: it wins over whatever the
|
||||||
// widget would draw, so it has to win over what the widget says too.
|
// widget would draw, so it has to win over what the widget says too.
|
||||||
@@ -252,7 +252,7 @@ impl<'a> Painter<'a> {
|
|||||||
child: &StrongWidget<W>,
|
child: &StrongWidget<W>,
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
) -> Option<Len> {
|
) -> Option<LayoutLen> {
|
||||||
let declared = self.declared_lens(child);
|
let declared = self.declared_lens(child);
|
||||||
let align = self.rsc.widgets().alignment(child.id());
|
let align = self.rsc.widgets().alignment(child.id());
|
||||||
let local = declared_box(region, declared, align);
|
let local = declared_box(region, declared, align);
|
||||||
@@ -472,7 +472,7 @@ impl<W: ?Sized> DrawResult<'_, '_, W> {
|
|||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(self, axis: Axis) -> Len {
|
pub fn len(self, axis: Axis) -> LayoutLen {
|
||||||
self.size().axis(axis)
|
self.size().axis(axis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -505,7 +505,7 @@ impl PrimitiveLike for &TextureHandle {
|
|||||||
/// What a widget declares a length of its box to be. `leftover` is not one: a
|
/// What a widget declares a length of its box to be. `leftover` is not one: a
|
||||||
/// share of what is left over is only a length to the widget dividing one,
|
/// share of what is left over is only a length to the widget dividing one,
|
||||||
/// so it passes up in the size instead.
|
/// so it passes up in the size instead.
|
||||||
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<Len>; 2] {
|
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<LayoutLen>; 2] {
|
||||||
let rules = widgets.size_rules(id);
|
let rules = widgets.size_rules(id);
|
||||||
let widget = widgets.get_dyn(id);
|
let widget = widgets.get_dyn(id);
|
||||||
AXES.map(|axis| {
|
AXES.map(|axis| {
|
||||||
@@ -537,7 +537,7 @@ pub(crate) fn placed_box(
|
|||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
size: Size,
|
size: Size,
|
||||||
align: RegionAlign,
|
align: RegionAlign,
|
||||||
declared: [Option<Len>; 2],
|
declared: [Option<LayoutLen>; 2],
|
||||||
) -> UiRegion {
|
) -> UiRegion {
|
||||||
let mut placed = region;
|
let mut placed = region;
|
||||||
for (axis, declared) in AXES.into_iter().zip(declared) {
|
for (axis, declared) in AXES.into_iter().zip(declared) {
|
||||||
@@ -546,7 +546,7 @@ pub(crate) fn placed_box(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let span = placed.axis_mut(axis);
|
let span = placed.axis_mut(axis);
|
||||||
let len = span.len().scale(reported.rel) + UiScalar::from_parts(Rel::ZERO, reported.px);
|
let len = span.len().scale(reported.rel) + Len::from_parts(Rel::ZERO, reported.px);
|
||||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||||
span.end = span.start + len;
|
span.end = span.start + len;
|
||||||
}
|
}
|
||||||
@@ -559,13 +559,13 @@ pub(crate) fn placed_box(
|
|||||||
/// space hands back the same length, so this is the identity for it.
|
/// space hands back the same length, so this is the identity for it.
|
||||||
pub(crate) fn declared_box(
|
pub(crate) fn declared_box(
|
||||||
mut region: UiRegion,
|
mut region: UiRegion,
|
||||||
declared: [Option<Len>; 2],
|
declared: [Option<LayoutLen>; 2],
|
||||||
align: RegionAlign,
|
align: RegionAlign,
|
||||||
) -> UiRegion {
|
) -> UiRegion {
|
||||||
for (axis, len) in AXES.into_iter().zip(declared) {
|
for (axis, len) in AXES.into_iter().zip(declared) {
|
||||||
let Some(len) = len else { continue };
|
let Some(len) = len else { continue };
|
||||||
let span = region.axis_mut(axis);
|
let span = region.axis_mut(axis);
|
||||||
let len = UiScalar::from_parts(len.rel, len.px);
|
let len = Len::from_parts(len.rel, len.px);
|
||||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||||
span.end = span.start + len;
|
span.end = span.start + len;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-17
@@ -2,9 +2,9 @@
|
|||||||
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
||||||
use crate::ui::painter::{declared_box, declared_lens, placed_box};
|
use crate::ui::painter::{declared_box, declared_lens, placed_box};
|
||||||
use crate::{
|
use crate::{
|
||||||
ActiveData, Axis, DrawLayers, Holds, IdLike, Len, MaskIdx, MoveIdx, Moves, Painter,
|
ActiveData, Axis, DrawLayers, Holds, IdLike, LayoutLen, Len, MaskIdx, MoveIdx, Moves, Painter,
|
||||||
PixelRegion, PxVec2, RegionAlign, Rel, Size, StrongWidget, UiRegion, UiRsc, UiScalar, UiSpan,
|
PixelRegion, PxVec2, RegionAlign, Rel, Size, StrongWidget, UiRegion, UiRsc, UiSpan, Weight,
|
||||||
Weight, WidgetId, Widgets,
|
WidgetId, Widgets,
|
||||||
util::{HashMap, Vec2},
|
util::{HashMap, Vec2},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,14 +75,8 @@ impl UiRenderState {
|
|||||||
/// downstream has to know the output's size to resolve a position.
|
/// downstream has to know the output's size to resolve a position.
|
||||||
fn write_root(&mut self) {
|
fn write_root(&mut self) {
|
||||||
let region = UiRegion::new(
|
let region = UiRegion::new(
|
||||||
UiSpan::new(
|
UiSpan::new(Len::ZERO, Len::from_parts(Rel::ZERO, self.output_size.x)),
|
||||||
UiScalar::ZERO,
|
UiSpan::new(Len::ZERO, Len::from_parts(Rel::ZERO, self.output_size.y)),
|
||||||
UiScalar::from_parts(Rel::ZERO, self.output_size.x),
|
|
||||||
),
|
|
||||||
UiSpan::new(
|
|
||||||
UiScalar::ZERO,
|
|
||||||
UiScalar::from_parts(Rel::ZERO, self.output_size.y),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
match self.root_move == MoveIdx::NONE {
|
match self.root_move == MoveIdx::NONE {
|
||||||
true => self.root_move = self.moves.push(MoveIdx::NONE, region),
|
true => self.root_move = self.moves.push(MoveIdx::NONE, region),
|
||||||
@@ -255,8 +249,8 @@ impl UiRenderState {
|
|||||||
let reported = answer.0.axis(axis);
|
let reported = answer.0.axis(axis);
|
||||||
let placed_len =
|
let placed_len =
|
||||||
match reported.leftover != Weight::ZERO || declared[axis as usize].is_some() {
|
match reported.leftover != Weight::ZERO || declared[axis as usize].is_some() {
|
||||||
true => UiScalar::FULL,
|
true => Len::FULL,
|
||||||
false => UiScalar::from_parts(reported.rel, reported.px),
|
false => Len::from_parts(reported.rel, reported.px),
|
||||||
};
|
};
|
||||||
settled.1[axis as usize] =
|
settled.1[axis as usize] =
|
||||||
settled.1[axis as usize].and(drawing_holds[axis as usize].through(placed_len));
|
settled.1[axis as usize].and(drawing_holds[axis as usize].through(placed_len));
|
||||||
@@ -765,10 +759,10 @@ impl UiRenderState {
|
|||||||
let size = Size {
|
let size = Size {
|
||||||
x: widget
|
x: widget
|
||||||
.and_then(|w| w.size_hint(Axis::X))
|
.and_then(|w| w.size_hint(Axis::X))
|
||||||
.unwrap_or(Len::ZERO),
|
.unwrap_or(LayoutLen::ZERO),
|
||||||
y: widget
|
y: widget
|
||||||
.and_then(|w| w.size_hint(Axis::Y))
|
.and_then(|w| w.size_hint(Axis::Y))
|
||||||
.unwrap_or(Len::ZERO),
|
.unwrap_or(LayoutLen::ZERO),
|
||||||
};
|
};
|
||||||
self.active.insert(
|
self.active.insert(
|
||||||
id,
|
id,
|
||||||
@@ -1079,7 +1073,7 @@ impl RegionRemap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_scalar(self, scalar: UiScalar, from: UiSpan, to: UiSpan) -> UiScalar {
|
fn apply_scalar(self, scalar: Len, from: UiSpan, to: UiSpan) -> Len {
|
||||||
let extent = from.end.rel - from.start.rel;
|
let extent = from.end.rel - from.start.rel;
|
||||||
// A box that only moved, or that has no relative extent to divide,
|
// A box that only moved, or that has no relative extent to divide,
|
||||||
// carries its parts by moving them, which is exact. Dividing to find
|
// carries its parts by moving them, which is exact. Dividing to find
|
||||||
@@ -1100,7 +1094,7 @@ impl RegionRemap {
|
|||||||
let from_px = fraction.lerp(from.start.px, from.end.px);
|
let from_px = fraction.lerp(from.start.px, from.end.px);
|
||||||
let to_rel = fraction.lerp(to.start.rel, to.end.rel);
|
let to_rel = fraction.lerp(to.start.rel, to.end.rel);
|
||||||
let to_px = fraction.lerp(to.start.px, to.end.px);
|
let to_px = fraction.lerp(to.start.px, to.end.px);
|
||||||
UiScalar::from_parts(to_rel, scalar.px - from_px + to_px)
|
Len::from_parts(to_rel, scalar.px - from_px + to_px)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Axis, Len, Painter, Size};
|
use crate::{Axis, LayoutLen, Painter, Size};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
@@ -24,7 +24,7 @@ pub trait Widget: Any {
|
|||||||
/// An exact length the widget can give without a painter or its children.
|
/// An exact length the widget can give without a painter or its children.
|
||||||
/// Optional, and saves a draw rather than changing one: a hint that
|
/// Optional, and saves a draw rather than changing one: a hint that
|
||||||
/// disagrees with the eventual draw fails a debug assertion.
|
/// disagrees with the eventual draw fails a debug assertion.
|
||||||
fn size_hint(&self, _axis: Axis) -> Option<Len> {
|
fn size_hint(&self, _axis: Axis) -> Option<LayoutLen> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,8 +35,8 @@ impl Widget for () {
|
|||||||
Size::default()
|
Size::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self, _axis: Axis) -> Option<Len> {
|
fn size_hint(&self, _axis: Axis) -> Option<LayoutLen> {
|
||||||
Some(Len::default())
|
Some(LayoutLen::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Axis, Len, Weight};
|
use crate::{Axis, LayoutLen, Weight};
|
||||||
|
|
||||||
/// What a widget's length on one axis is, as a rule its parent applies where
|
/// What a widget's length on one axis is, as a rule its parent applies where
|
||||||
/// it draws it rather than an answer the widget gives about itself.
|
/// it draws it rather than an answer the widget gives about itself.
|
||||||
@@ -14,7 +14,7 @@ pub enum SizeRule {
|
|||||||
#[default]
|
#[default]
|
||||||
Free,
|
Free,
|
||||||
/// This length, whatever the widget reports.
|
/// This length, whatever the widget reports.
|
||||||
Exact(Len),
|
Exact(LayoutLen),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeRule {
|
impl SizeRule {
|
||||||
@@ -22,7 +22,7 @@ impl SizeRule {
|
|||||||
/// give one. `leftover` is never among them: a share is a length only to
|
/// give one. `leftover` is never among them: a share is a length only to
|
||||||
/// whoever divides one, so it passes up in the reported size instead and
|
/// whoever divides one, so it passes up in the reported size instead and
|
||||||
/// is resolved there.
|
/// is resolved there.
|
||||||
pub fn declared(&self) -> Option<Len> {
|
pub fn declared(&self) -> Option<LayoutLen> {
|
||||||
match self {
|
match self {
|
||||||
Self::Exact(len) if len.leftover == Weight::ZERO => Some(*len),
|
Self::Exact(len) if len.leftover == Weight::ZERO => Some(*len),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -33,7 +33,7 @@ impl SizeRule {
|
|||||||
/// share is a length the widget's parent still has to divide, so it is
|
/// share is a length the widget's parent still has to divide, so it is
|
||||||
/// known here and resolved there -- unlike `declared`, which is only the
|
/// known here and resolved there -- unlike `declared`, which is only the
|
||||||
/// ones that give a box directly.
|
/// ones that give a box directly.
|
||||||
pub fn known(&self) -> Option<Len> {
|
pub fn known(&self) -> Option<LayoutLen> {
|
||||||
match self {
|
match self {
|
||||||
Self::Free => None,
|
Self::Free => None,
|
||||||
Self::Exact(len) => Some(*len),
|
Self::Exact(len) => Some(*len),
|
||||||
@@ -41,7 +41,7 @@ impl SizeRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The length a widget reporting `reported` ends up with.
|
/// The length a widget reporting `reported` ends up with.
|
||||||
pub fn apply(&self, reported: Len) -> Len {
|
pub fn apply(&self, reported: LayoutLen) -> LayoutLen {
|
||||||
match self {
|
match self {
|
||||||
Self::Free => reported,
|
Self::Free => reported,
|
||||||
Self::Exact(len) => *len,
|
Self::Exact(len) => *len,
|
||||||
@@ -49,14 +49,14 @@ impl SizeRule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Len> for SizeRule {
|
impl From<LayoutLen> for SizeRule {
|
||||||
fn from(len: Len) -> Self {
|
fn from(len: LayoutLen) -> Self {
|
||||||
Self::Exact(len)
|
Self::Exact(len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Len>> for SizeRule {
|
impl From<Option<LayoutLen>> for SizeRule {
|
||||||
fn from(len: Option<Len>) -> Self {
|
fn from(len: Option<LayoutLen>) -> Self {
|
||||||
len.map_or(Self::Free, Self::Exact)
|
len.map_or(Self::Free, Self::Exact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -165,7 +165,7 @@ impl Harness {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Changes a length rule after the fact, the way `.width()` sets one.
|
/// Changes a length rule after the fact, the way `.width()` sets one.
|
||||||
pub fn set_len(&mut self, id: impl IdLike, axis: Axis, len: impl Into<Len>) {
|
pub fn set_len(&mut self, id: impl IdLike, axis: Axis, len: impl Into<LayoutLen>) {
|
||||||
self.rsc
|
self.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
.set_size_rule(id, axis, SizeRule::Exact(len.into()));
|
.set_size_rule(id, axis, SizeRule::Exact(len.into()));
|
||||||
|
|||||||
+5
-5
@@ -9,7 +9,7 @@ use crate::prelude::*;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// The declared lengths of one widget carrying a size rule, by axis.
|
/// The declared lengths of one widget carrying a size rule, by axis.
|
||||||
pub type Lens = [Option<Len>; 2];
|
pub type Lens = [Option<LayoutLen>; 2];
|
||||||
|
|
||||||
/// Where one widget carrying an alignment sits, by axis. `None` uses the
|
/// Where one widget carrying an alignment sits, by axis. `None` uses the
|
||||||
/// centered default.
|
/// centered default.
|
||||||
@@ -181,10 +181,10 @@ impl<Rsc: UiRsc + 'static> Grow<'_, Rsc> {
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&mut self) -> Option<Len> {
|
fn len(&mut self) -> Option<LayoutLen> {
|
||||||
match self.rng.below(4) {
|
match self.rng.below(4) {
|
||||||
0 => Some(Len::px(20.0 + self.rng.below(180) as f32)),
|
0 => Some(LayoutLen::px(20.0 + self.rng.below(180) as f32)),
|
||||||
1 => Some(Len::LEFTOVER),
|
1 => Some(LayoutLen::LEFTOVER),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,7 +367,7 @@ impl<Rsc: UiRsc + 'static> Grow<'_, Rsc> {
|
|||||||
if dir.axis == Axis::X {
|
if dir.axis == Axis::X {
|
||||||
self.rsc
|
self.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
.set_size_rules(id, None, Some(Len::rel(1.0)));
|
.set_size_rules(id, None, Some(LayoutLen::rel(1.0)));
|
||||||
}
|
}
|
||||||
self.tree.ids.push(id.id());
|
self.tree.ids.push(id.id());
|
||||||
self.tree.spans.push(Spanned { id, spares, grown });
|
self.tree.spans.push(Spanned { id, spares, grown });
|
||||||
|
|||||||
+2
-2
@@ -11,8 +11,8 @@ impl Widget for Image {
|
|||||||
Size::px(self.handle.size())
|
Size::px(self.handle.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self, axis: Axis) -> Option<Len> {
|
fn size_hint(&self, axis: Axis) -> Option<LayoutLen> {
|
||||||
Some(Len::px(self.handle.size().axis(axis)))
|
Some(LayoutLen::px(self.handle.size().axis(axis)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ impl Widget for Pad {
|
|||||||
.widget_aligned(&self.inner, self.padding.region(), RegionAlign::NEAR)
|
.widget_aligned(&self.inner, self.padding.region(), RegionAlign::NEAR)
|
||||||
.size();
|
.size();
|
||||||
Size {
|
Size {
|
||||||
x: Len {
|
x: LayoutLen {
|
||||||
px: inner.x.px + self.padding.left + self.padding.right,
|
px: inner.x.px + self.padding.left + self.padding.right,
|
||||||
..inner.x
|
..inner.x
|
||||||
},
|
},
|
||||||
y: Len {
|
y: LayoutLen {
|
||||||
px: inner.y.px + self.padding.top + self.padding.bottom,
|
px: inner.y.px + self.padding.top + self.padding.bottom,
|
||||||
..inner.y
|
..inner.y
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ impl Widget for Scroll {
|
|||||||
if moved || self.content_len != self.container_len {
|
if moved || self.content_len != self.container_len {
|
||||||
let offset = UiVec2::from_axis(
|
let offset = UiVec2::from_axis(
|
||||||
self.axis,
|
self.axis,
|
||||||
UiScalar::from_parts(Rel::ZERO, anchor - self.amt),
|
Len::from_parts(Rel::ZERO, anchor - self.amt),
|
||||||
UiScalar::ZERO,
|
Len::ZERO,
|
||||||
);
|
);
|
||||||
region = region.offset(offset);
|
region = region.offset(offset);
|
||||||
region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len);
|
region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len);
|
||||||
|
|||||||
+11
-11
@@ -12,10 +12,10 @@ impl Widget for Span {
|
|||||||
let axis = self.dir.axis;
|
let axis = self.dir.axis;
|
||||||
// A length for every child before their final boxes are chosen: from
|
// A length for every child before their final boxes are chosen: from
|
||||||
// a hint where one exists, and from drawing otherwise.
|
// a hint where one exists, and from drawing otherwise.
|
||||||
let mut cursor = UiScalar::rel_min();
|
let mut cursor = Len::rel_min();
|
||||||
let mut lens = Vec::with_capacity(self.children.len());
|
let mut lens = Vec::with_capacity(self.children.len());
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
let mut span = UiSpan::new(cursor, UiScalar::rel_max());
|
let mut span = UiSpan::new(cursor, Len::rel_max());
|
||||||
if self.dir.sign == Sign::Neg {
|
if self.dir.sign == Sign::Neg {
|
||||||
span.flip();
|
span.flip();
|
||||||
}
|
}
|
||||||
@@ -33,9 +33,9 @@ impl Widget for Span {
|
|||||||
.gap
|
.gap
|
||||||
.mul_int(self.children.len().saturating_sub(1) as i32);
|
.mul_int(self.children.len().saturating_sub(1) as i32);
|
||||||
let total = lens.iter().fold(
|
let total = lens.iter().fold(
|
||||||
Len {
|
LayoutLen {
|
||||||
px: gaps,
|
px: gaps,
|
||||||
..Len::ZERO
|
..LayoutLen::ZERO
|
||||||
},
|
},
|
||||||
|sum, len| sum + *len,
|
|sum, len| sum + *len,
|
||||||
);
|
);
|
||||||
@@ -89,11 +89,11 @@ impl Widget for Span {
|
|||||||
// from the last child: the share of the room is rounded, and taking
|
// from the last child: the share of the room is rounded, and taking
|
||||||
// each from the one before it would carry every rounding along the
|
// each from the one before it would carry every rounding along the
|
||||||
// row.
|
// row.
|
||||||
let mut fixed = UiScalar::rel_min();
|
let mut fixed = Len::rel_min();
|
||||||
let mut taken = Weight::ZERO;
|
let mut taken = Weight::ZERO;
|
||||||
let room = UiScalar::rel_max() - UiScalar::from_parts(total.rel, total.px);
|
let room = Len::rel_max() - Len::from_parts(total.rel, total.px);
|
||||||
let mut start = UiScalar::rel_min();
|
let mut start = Len::rel_min();
|
||||||
let mut ortho = Len::ZERO;
|
let mut ortho = LayoutLen::ZERO;
|
||||||
for (child, len) in self.children.iter().zip(&lens) {
|
for (child, len) in self.children.iter().zip(&lens) {
|
||||||
// A child asking for nothing but a part of what is left over,
|
// A child asking for nothing but a part of what is left over,
|
||||||
// when nothing is, is not drawn at all. One that also asked for
|
// when nothing is, is not drawn at all. One that also asked for
|
||||||
@@ -125,7 +125,7 @@ impl Widget for Span {
|
|||||||
// A scalable child therefore makes Children scalable too;
|
// A scalable child therefore makes Children scalable too;
|
||||||
// only fixed children are compared with one another.
|
// only fixed children are compared with one another.
|
||||||
if used.rel != Rel::ZERO || used.leftover != Weight::ZERO {
|
if used.rel != Rel::ZERO || used.leftover != Weight::ZERO {
|
||||||
ortho = Len::LEFTOVER;
|
ortho = LayoutLen::LEFTOVER;
|
||||||
} else if ortho.leftover == Weight::ZERO {
|
} else if ortho.leftover == Weight::ZERO {
|
||||||
ortho.px = ortho.px.max(used.px);
|
ortho.px = ortho.px.max(used.px);
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ impl Widget for Span {
|
|||||||
let along = total;
|
let along = total;
|
||||||
let ortho = match shrinks {
|
let ortho = match shrinks {
|
||||||
true => ortho,
|
true => ortho,
|
||||||
false => Len::rel(1.0),
|
false => LayoutLen::rel(1.0),
|
||||||
};
|
};
|
||||||
Size::from_axis(axis, along, ortho)
|
Size::from_axis(axis, along, ortho)
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ impl Widget for Span {
|
|||||||
/// Where a row has reached: everything fixed before this point, which is a
|
/// Where a row has reached: everything fixed before this point, which is a
|
||||||
/// sum and exact, plus the share of the room the weights so far are worth,
|
/// sum and exact, plus the share of the room the weights so far are worth,
|
||||||
/// which is one rounding wherever it is asked for.
|
/// which is one rounding wherever it is asked for.
|
||||||
fn shared(fixed: UiScalar, taken: Weight, weight: Weight, room: UiScalar) -> UiScalar {
|
fn shared(fixed: Len, taken: Weight, weight: Weight, room: Len) -> Len {
|
||||||
if taken == Weight::ZERO {
|
if taken == Weight::ZERO {
|
||||||
return fixed;
|
return fixed;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -38,8 +38,8 @@ impl Widget for Rect {
|
|||||||
Size::LEFTOVER
|
Size::LEFTOVER
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self, _: Axis) -> Option<Len> {
|
fn size_hint(&self, _: Axis) -> Option<LayoutLen> {
|
||||||
Some(Len::LEFTOVER)
|
Some(LayoutLen::LEFTOVER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ widget_trait! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn width(self, len: impl Into<Len>) -> impl WidgetIdFn<Rsc, WL::Widget> {
|
fn width(self, len: impl Into<LayoutLen>) -> impl WidgetIdFn<Rsc, WL::Widget> {
|
||||||
let len = len.into();
|
let len = len.into();
|
||||||
move |state| {
|
move |state| {
|
||||||
let id = self.add(state);
|
let id = self.add(state);
|
||||||
@@ -71,7 +71,7 @@ widget_trait! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn height(self, len: impl Into<Len>) -> impl WidgetIdFn<Rsc, WL::Widget> {
|
fn height(self, len: impl Into<LayoutLen>) -> impl WidgetIdFn<Rsc, WL::Widget> {
|
||||||
let len = len.into();
|
let len = len.into();
|
||||||
move |state| {
|
move |state| {
|
||||||
let id = self.add(state);
|
let id = self.add(state);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ fn a_span_ruled_across_itself_does_not_measure_its_children_there() {
|
|||||||
let span = (child,).span(Dir::RIGHT).height(rel(1.0)).add(&mut h.rsc);
|
let span = (child,).span(Dir::RIGHT).height(rel(1.0)).add(&mut h.rsc);
|
||||||
h.set_root(span);
|
h.set_root(span);
|
||||||
|
|
||||||
assert_eq!(h.render.active[&span.id()].size.y, Len::rel(1.0));
|
assert_eq!(h.render.active[&span.id()].size.y, LayoutLen::rel(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -38,7 +38,7 @@ fn a_span_reports_its_tallest_fixed_child() {
|
|||||||
let span = (short, tall).span(Dir::RIGHT).add(&mut h.rsc);
|
let span = (short, tall).span(Dir::RIGHT).add(&mut h.rsc);
|
||||||
h.set_root(span);
|
h.set_root(span);
|
||||||
|
|
||||||
assert_eq!(h.render.active[&span.id()].size.y, Len::px(70.0));
|
assert_eq!(h.render.active[&span.id()].size.y, LayoutLen::px(70.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -331,7 +331,7 @@ fn drawn_edges(h: &Harness, id: WidgetId, axis: Axis) -> (f32, f32) {
|
|||||||
let region = h.render.moves.resolve(active.parent_move, active.region);
|
let region = h.render.moves.resolve(active.parent_move, active.region);
|
||||||
let dim = h.size().axis(axis);
|
let dim = h.size().axis(axis);
|
||||||
let snap = |v: f32| (v + Px::STEP.to_f32() * 0.5).floor();
|
let snap = |v: f32| (v + Px::STEP.to_f32() * 0.5).floor();
|
||||||
let edge = |s: UiScalar| snap(s.rel.to_f32() * dim) + snap(s.px.to_f32());
|
let edge = |s: Len| snap(s.rel.to_f32() * dim) + snap(s.px.to_f32());
|
||||||
let span = region.axis(axis);
|
let span = region.axis(axis);
|
||||||
(edge(span.start), edge(span.end))
|
(edge(span.start), edge(span.end))
|
||||||
}
|
}
|
||||||
@@ -343,7 +343,7 @@ fn hairline(h: &mut Harness, marks: &mut Vec<WidgetId>) -> StrongWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn share(h: &mut Harness, inner: StrongWidget, ratio: f32) -> StrongWidget {
|
fn share(h: &mut Harness, inner: StrongWidget, ratio: f32) -> StrongWidget {
|
||||||
h.set_len(&inner, Axis::X, Len::leftover(ratio));
|
h.set_len(&inner, Axis::X, LayoutLen::leftover(ratio));
|
||||||
inner
|
inner
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ fn only_a_pure_leftover_child_disappears_when_nothing_is_left() {
|
|||||||
let mut h = Harness::new((100, 20));
|
let mut h = Harness::new((100, 20));
|
||||||
let fixed = rect(Color::RED).width(100).add(&mut h.rsc);
|
let fixed = rect(Color::RED).width(100).add(&mut h.rsc);
|
||||||
let mixed = rect(Color::BLUE)
|
let mixed = rect(Color::BLUE)
|
||||||
.width(Len::px(20) + Len::LEFTOVER)
|
.width(LayoutLen::px(20) + LayoutLen::LEFTOVER)
|
||||||
.add(&mut h.rsc);
|
.add(&mut h.rsc);
|
||||||
h.set_root((fixed, mixed).span(Dir::RIGHT));
|
h.set_root((fixed, mixed).span(Dir::RIGHT));
|
||||||
|
|
||||||
|
|||||||
@@ -125,10 +125,7 @@ fn moving_an_ordinary_subtree_remaps_its_mask() {
|
|||||||
let active = &h.render.active[&masked.id()];
|
let active = &h.render.active[&masked.id()];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
h.rsc.ui().masks[active.mask.idx()].region,
|
h.rsc.ui().masks[active.mask.idx()].region,
|
||||||
UiRegion::new(
|
UiRegion::new(UiSpan::new(Len::px(150.0), Len::rel_max()), UiSpan::FULL,)
|
||||||
UiSpan::new(UiScalar::px(150.0), UiScalar::rel_max()),
|
|
||||||
UiSpan::FULL,
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
assert_corners!(h, inner, (150, 0), (400, 200));
|
assert_corners!(h, inner, (150, 0), (400, 200));
|
||||||
}
|
}
|
||||||
@@ -312,7 +309,7 @@ fn a_span_ruled_across_itself_moves_its_child_without_redrawing_it() {
|
|||||||
|
|
||||||
assert_eq!(draws.get(), settled);
|
assert_eq!(draws.get(), settled);
|
||||||
assert_corners!(h, leaf, (0, 0), (400, 100));
|
assert_corners!(h, leaf, (0, 0), (400, 100));
|
||||||
assert_eq!(h.render.active[&span.id()].size.y, Len::rel(1.0));
|
assert_eq!(h.render.active[&span.id()].size.y, LayoutLen::rel(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The output is the root of the box chain, so a resize is a box that changed
|
/// The output is the root of the box chain, so a resize is a box that changed
|
||||||
@@ -407,12 +404,12 @@ fn a_box_change_within_one_step_is_not_a_change() {
|
|||||||
|
|
||||||
let step = Px::STEP.to_f32();
|
let step = Px::STEP.to_f32();
|
||||||
for part in [0.1, 0.2, 0.3] {
|
for part in [0.1, 0.2, 0.3] {
|
||||||
h.rsc[first].size.x = Len::px(100.0 + step * part);
|
h.rsc[first].size.x = LayoutLen::px(100.0 + step * part);
|
||||||
h.frame();
|
h.frame();
|
||||||
assert_eq!(draws.get(), settled);
|
assert_eq!(draws.get(), settled);
|
||||||
}
|
}
|
||||||
|
|
||||||
h.rsc[first].size.x = Len::px(100.0 + step);
|
h.rsc[first].size.x = LayoutLen::px(100.0 + step);
|
||||||
h.frame();
|
h.frame();
|
||||||
assert_eq!(draws.get(), settled + 1);
|
assert_eq!(draws.get(), settled + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,11 +281,11 @@ struct Wider {
|
|||||||
impl Widget for Wider {
|
impl Widget for Wider {
|
||||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||||
Size {
|
Size {
|
||||||
x: Len {
|
x: LayoutLen {
|
||||||
px: painter.px_len(Axis::X) + Px::from_f32(self.extra),
|
px: painter.px_len(Axis::X) + Px::from_f32(self.extra),
|
||||||
..Len::ZERO
|
..LayoutLen::ZERO
|
||||||
},
|
},
|
||||||
y: Len::LEFTOVER,
|
y: LayoutLen::LEFTOVER,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,7 +341,7 @@ fn plant_boundary(h: &mut Harness, swapped: bool) -> (Vec<WidgetId>, [WeakWidget
|
|||||||
let whole = rect(Color::RED).add(&mut h.rsc);
|
let whole = rect(Color::RED).add(&mut h.rsc);
|
||||||
h.rsc
|
h.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
.set_size_rules(whole, None, Some(Len::rel(1.0)));
|
.set_size_rules(whole, None, Some(LayoutLen::rel(1.0)));
|
||||||
let mut inner_children: Vec<StrongWidget> = vec![
|
let mut inner_children: Vec<StrongWidget> = vec![
|
||||||
measured.add_strong(&mut h.rsc),
|
measured.add_strong(&mut h.rsc),
|
||||||
whole.add_strong(&mut h.rsc),
|
whole.add_strong(&mut h.rsc),
|
||||||
@@ -357,7 +357,7 @@ fn plant_boundary(h: &mut Harness, swapped: bool) -> (Vec<WidgetId>, [WeakWidget
|
|||||||
.add(&mut h.rsc);
|
.add(&mut h.rsc);
|
||||||
h.rsc
|
h.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
.set_size_rules(inner, None, Some(Len::px(198.0)));
|
.set_size_rules(inner, None, Some(LayoutLen::px(198.0)));
|
||||||
// One more span above it: without a box composed through it, both trees
|
// One more span above it: without a box composed through it, both trees
|
||||||
// round the same way and the boundary is never crossed.
|
// round the same way and the boundary is never crossed.
|
||||||
let outer = (inner,).span(Dir::DOWN).add(&mut h.rsc);
|
let outer = (inner,).span(Dir::DOWN).add(&mut h.rsc);
|
||||||
|
|||||||
+3
-3
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
use iris::prelude::*;
|
use iris::prelude::*;
|
||||||
use iris_core::{
|
use iris_core::{
|
||||||
MaskIdx, MoveIdx, PrimitiveInst, RectPrimitive, UiData, UiRegion, UiRenderNode, UiRenderState,
|
Len, MaskIdx, MoveIdx, PrimitiveInst, RectPrimitive, UiData, UiRegion, UiRenderNode,
|
||||||
UiScalar, UiSpan,
|
UiRenderState, UiSpan,
|
||||||
};
|
};
|
||||||
use wgpu::{Color as GpuColor, *};
|
use wgpu::{Color as GpuColor, *};
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ fn fill(ui: &mut UiData, render: &mut UiRenderState, depth: usize) {
|
|||||||
slot = render.moves.push(slot, UiRegion::FULL);
|
slot = render.moves.push(slot, UiRegion::FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
let px = |v: f32| UiScalar::px(v);
|
let px = |v: f32| Len::px(v);
|
||||||
for i in 0..INSTANCES {
|
for i in 0..INSTANCES {
|
||||||
let x = (i % (SIZE as usize / 2)) as f32 * 2.0;
|
let x = (i % (SIZE as usize / 2)) as f32 * 2.0;
|
||||||
let y = (i / (SIZE as usize / 2)) as f32;
|
let y = (i / (SIZE as usize / 2)) as f32;
|
||||||
|
|||||||
+2
-2
@@ -61,8 +61,8 @@ fn plant(h: &mut Harness, seed: u64, edits: &Edits) -> Tree {
|
|||||||
|
|
||||||
fn resize_one(h: &mut Harness, tree: &Tree, idx: usize, rng: &mut Rng) -> Lens {
|
fn resize_one(h: &mut Harness, tree: &Tree, idx: usize, rng: &mut Rng) -> Lens {
|
||||||
let lens = [
|
let lens = [
|
||||||
Some(Len::px(20.0 + rng.below(180) as f32)),
|
Some(LayoutLen::px(20.0 + rng.below(180) as f32)),
|
||||||
Some(Len::px(20.0 + rng.below(180) as f32)),
|
Some(LayoutLen::px(20.0 + rng.below(180) as f32)),
|
||||||
];
|
];
|
||||||
h.rsc
|
h.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ fn layout_cost() {
|
|||||||
trace_selected(&tree);
|
trace_selected(&tree);
|
||||||
let sized = tree.sized[0];
|
let sized = tree.sized[0];
|
||||||
run("size", frames, &mut harness, move |harness, frame| {
|
run("size", frames, &mut harness, move |harness, frame| {
|
||||||
let len = Len::px(100.0 + (frame % 2) as f32 * 40.0);
|
let len = LayoutLen::px(100.0 + (frame % 2) as f32 * 40.0);
|
||||||
harness
|
harness
|
||||||
.rsc
|
.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
|
|||||||
@@ -94,7 +94,11 @@ fn build(h: &mut Harness, rows: usize) -> Vec<WidgetId> {
|
|||||||
let mut col = Span::empty(Dir::DOWN);
|
let mut col = Span::empty(Dir::DOWN);
|
||||||
for _ in 0..rows {
|
for _ in 0..rows {
|
||||||
let mut row = Span::empty(Dir::RIGHT);
|
let mut row = Span::empty(Dir::RIGHT);
|
||||||
row.push(rect(Color::RED).width(Len::px(40.0)).add_strong(&mut h.rsc));
|
row.push(
|
||||||
|
rect(Color::RED)
|
||||||
|
.width(LayoutLen::px(40.0))
|
||||||
|
.add_strong(&mut h.rsc),
|
||||||
|
);
|
||||||
let mut body = Span::empty(Dir::DOWN);
|
let mut body = Span::empty(Dir::DOWN);
|
||||||
let para = wtext(words(&mut rng, 12, 52))
|
let para = wtext(words(&mut rng, 12, 52))
|
||||||
.size(16)
|
.size(16)
|
||||||
|
|||||||
+10
-10
@@ -72,7 +72,7 @@ enum Node {
|
|||||||
Stack(Vec<Node>),
|
Stack(Vec<Node>),
|
||||||
Pad(f32, Box<Node>),
|
Pad(f32, Box<Node>),
|
||||||
Aligned(u8, u8, Box<Node>),
|
Aligned(u8, u8, Box<Node>),
|
||||||
Sized(Option<Len>, Option<Len>, Box<Node>),
|
Sized(Option<LayoutLen>, Option<LayoutLen>, Box<Node>),
|
||||||
Scroll(bool, Box<Node>),
|
Scroll(bool, Box<Node>),
|
||||||
Branch(Box<Node>, Box<Node>, Box<Node>, f32),
|
Branch(Box<Node>, Box<Node>, Box<Node>, f32),
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ impl Node {
|
|||||||
if !*down {
|
if !*down {
|
||||||
h.rsc
|
h.rsc
|
||||||
.widgets_mut()
|
.widgets_mut()
|
||||||
.set_size_rules(handle, None, Some(Len::rel(1.0)));
|
.set_size_rules(handle, None, Some(LayoutLen::rel(1.0)));
|
||||||
}
|
}
|
||||||
spans.push(handle);
|
spans.push(handle);
|
||||||
handle.add_strong(&mut h.rsc)
|
handle.add_strong(&mut h.rsc)
|
||||||
@@ -191,7 +191,7 @@ impl Node {
|
|||||||
|
|
||||||
/// The lengths every `Sized` node would carry after `resized`, in the
|
/// The lengths every `Sized` node would carry after `resized`, in the
|
||||||
/// order `build` pushes them.
|
/// order `build` pushes them.
|
||||||
fn sized_lens(&self, out: &mut Vec<(Option<Len>, Option<Len>)>) {
|
fn sized_lens(&self, out: &mut Vec<(Option<LayoutLen>, Option<LayoutLen>)>) {
|
||||||
match self {
|
match self {
|
||||||
Node::Text(..) | Node::OneLine | Node::Rect => {}
|
Node::Text(..) | Node::OneLine | Node::Rect => {}
|
||||||
Node::Span(_, _, kids, _) | Node::Stack(kids) => {
|
Node::Span(_, _, kids, _) | Node::Stack(kids) => {
|
||||||
@@ -352,8 +352,8 @@ fn sized(rng: &mut Rng, inner: Node) -> Node {
|
|||||||
return inner;
|
return inner;
|
||||||
}
|
}
|
||||||
let len = |rng: &mut Rng| match rng.below(4) {
|
let len = |rng: &mut Rng| match rng.below(4) {
|
||||||
0 => Some(Len::px(20.0 + rng.below(180) as f32)),
|
0 => Some(LayoutLen::px(20.0 + rng.below(180) as f32)),
|
||||||
1 => Some(Len::LEFTOVER),
|
1 => Some(LayoutLen::LEFTOVER),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
Node::Sized(len(rng), len(rng), Box::new(inner))
|
Node::Sized(len(rng), len(rng), Box::new(inner))
|
||||||
@@ -368,9 +368,9 @@ fn grow(rng: &mut Rng, depth: usize) -> Node {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
let len = |rng: &mut Rng| match rng.below(4) {
|
let len = |rng: &mut Rng| match rng.below(4) {
|
||||||
0 => Some(Len::px(20.0 + rng.below(180) as f32)),
|
0 => Some(LayoutLen::px(20.0 + rng.below(180) as f32)),
|
||||||
1 => Some(Len::LEFTOVER),
|
1 => Some(LayoutLen::LEFTOVER),
|
||||||
2 => Some(Len::rel(0.25 + rng.below(3) as f32 * 0.25)),
|
2 => Some(LayoutLen::rel(0.25 + rng.below(3) as f32 * 0.25)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let kid = |rng: &mut Rng| {
|
let kid = |rng: &mut Rng| {
|
||||||
@@ -408,9 +408,9 @@ enum Case {
|
|||||||
|
|
||||||
/// A different declared length, kept the same kind so the change is to the
|
/// A different declared length, kept the same kind so the change is to the
|
||||||
/// value alone.
|
/// value alone.
|
||||||
fn resized_len(len: Option<Len>) -> Option<Len> {
|
fn resized_len(len: Option<LayoutLen>) -> Option<LayoutLen> {
|
||||||
let half = Rel::from_f32(0.5);
|
let half = Rel::from_f32(0.5);
|
||||||
len.map(|len| Len {
|
len.map(|len| LayoutLen {
|
||||||
px: len.px.mul(half) + Px::from_int(13),
|
px: len.px.mul(half) + Px::from_int(13),
|
||||||
rel: len.rel.mul(half),
|
rel: len.rel.mul(half),
|
||||||
leftover: len.leftover,
|
leftover: len.leftover,
|
||||||
|
|||||||
Reference in new issue
Block a user