Rename rest to leftover

The length kind that asks for a part of what is left once the fixed
lengths are taken is called leftover: Len::leftover(2), Len::LEFTOVER,
Size::LEFTOVER, Len::leftover the field, and apply_leftover. It says
what it is where "rest" reads as "the remainder of the list" as often as
"the remaining space", and every agent who has touched this has reached
for a third word for it.

Locals called rest that meant a region or a widget are renamed with it,
since the word now names something else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-15 14:22:52 -04:00
1 parent 9644971daf
commit 691e3eb23c
16 files changed
+98 -89

No files matched your search

+3
View File
@@ -25,6 +25,9 @@ tokio = { workspace = true, features = ["sync", "rt", "rt-multi-thread", "time"]
[workspace]
members = ["core", "macro", "rig-input"]
[profile.dev]
debug = 1
[workspace.package]
version = "0.1.0"
edition = "2024"
+27 -27
View File
@@ -11,7 +11,7 @@ pub struct Size {
pub struct Len {
pub px: f32,
pub rel: f32,
pub rest: f32,
pub leftover: f32,
}
impl<N: UiNum> From<N> for Len {
@@ -41,9 +41,9 @@ impl Size {
y: Len::ZERO,
};
pub const REST: Self = Self {
x: Len::REST,
y: Len::REST,
pub const LEFTOVER: Self = Self {
x: Len::LEFTOVER,
y: Len::LEFTOVER,
};
pub fn px(v: Vec2) -> Self {
@@ -60,17 +60,17 @@ impl Size {
}
}
pub fn rest(v: Vec2) -> Self {
pub fn leftover(v: Vec2) -> Self {
Self {
x: Len::rest(v.x),
y: Len::rest(v.y),
x: Len::leftover(v.x),
y: Len::leftover(v.y),
}
}
pub fn to_uivec2(self) -> UiVec2 {
UiVec2 {
x: self.x.apply_rest(),
y: self.y.apply_rest(),
x: self.x.apply_leftover(),
y: self.y.apply_leftover(),
}
}
@@ -99,18 +99,18 @@ impl Len {
pub const ZERO: Self = Self {
px: 0.0,
rel: 0.0,
rest: 0.0,
leftover: 0.0,
};
pub const REST: Self = Self {
pub const LEFTOVER: Self = Self {
px: 0.0,
rel: 0.0,
rest: 1.0,
leftover: 1.0,
};
pub fn apply_rest(&self) -> UiScalar {
pub fn apply_leftover(&self) -> UiScalar {
UiScalar {
rel: self.rel + if self.rest > 0.0 { 1.0 } else { 0.0 },
rel: self.rel + if self.leftover > 0.0 { 1.0 } else { 0.0 },
px: self.px,
}
}
@@ -119,21 +119,21 @@ impl Len {
Self {
px: px.to_f32(),
rel: 0.0,
rest: 0.0,
leftover: 0.0,
}
}
pub fn rel(rel: impl UiNum) -> Self {
Self {
px: 0.0,
rel: rel.to_f32(),
rest: 0.0,
leftover: 0.0,
}
}
pub fn rest(ratio: impl UiNum) -> Self {
pub fn leftover(ratio: impl UiNum) -> Self {
Self {
px: 0.0,
rel: 0.0,
rest: ratio.to_f32(),
leftover: ratio.to_f32(),
}
}
}
@@ -145,34 +145,34 @@ pub mod len_fns {
Len {
px: px.to_f32(),
rel: 0.0,
rest: 0.0,
leftover: 0.0,
}
}
pub fn rel(rel: impl UiNum) -> Len {
Len {
px: 0.0,
rel: rel.to_f32(),
rest: 0.0,
leftover: 0.0,
}
}
pub fn rest(ratio: impl UiNum) -> Len {
pub fn leftover(ratio: impl UiNum) -> Len {
Len {
px: 0.0,
rel: 0.0,
rest: ratio.to_f32(),
leftover: ratio.to_f32(),
}
}
}
impl_op!(Len Add add; px rel rest);
impl_op!(Len Sub sub; px rel rest);
impl_op!(Len Add add; px rel leftover);
impl_op!(Len Sub sub; px rel leftover);
impl_op!(Size Add add; x y);
impl_op!(Size Sub sub; x y);
impl Default for Len {
fn default() -> Self {
Self::rest(1.0)
Self::leftover(1.0)
}
}
@@ -190,8 +190,8 @@ impl std::fmt::Display for Len {
if self.rel != 0.0 {
write!(f, "{} rel;", self.rel)?;
}
if self.rest != 0.0 {
write!(f, "{} rest;", self.rest)?;
if self.leftover != 0.0 {
write!(f, "{} leftover;", self.leftover)?;
}
Ok(())
}
+3 -3
View File
@@ -112,7 +112,7 @@ impl<'a> Painter<'a> {
}
/// What a widget declares its lengths to be, which whoever draws it
/// resolves into its box. `rest` is not among them: a share of what is
/// resolves into its box. `leftover` is not among them: a part of what is
/// left over is only a length to the widget dividing one, so it passes
/// up in the size instead. Reading it depends on nothing -- the box that
/// comes of it is kept on the child, and `redraw` compares it there.
@@ -439,11 +439,11 @@ impl PrimitiveLike for &TextureHandle {
}
}
/// What a widget declares a length of its box to be. `rest` 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,
/// so it passes up in the size instead.
pub(crate) fn declared_len(widget: &dyn Widget, axis: Axis) -> Option<Len> {
widget.size_hint(axis).filter(|len| len.rest == 0.0)
widget.size_hint(axis).filter(|len| len.leftover == 0.0)
}
/// Takes a widget's declared lengths in the box `region` is given in, since a
+5 -5
View File
@@ -24,18 +24,18 @@ impl DefaultAppState for Client {
.color(Color::RED)
.sized((100, 100))
.center()
.width(rest(2)),
.width(leftover(2)),
(
rrect.color(Color::ORANGE),
rrect.color(Color::LIME).pad(10.0),
)
.span(Dir::RIGHT)
.width(rest(2)),
.width(leftover(2)),
rrect.color(Color::YELLOW),
)
.span(Dir::RIGHT)
.pad(10)
.width(rest(3)),
.width(leftover(3)),
)
.span(Dir::RIGHT)
.add(rsc);
@@ -121,11 +121,11 @@ impl DefaultAppState for Client {
.add(rsc);
let text_edit_scroll = (
msg_area.height(rest(1)),
msg_area.height(leftover(1)),
(
Rect::new(Color::WHITE.darker(0.9)),
(
add_text.width(rest(1)),
add_text.width(leftover(1)),
Rect::new(Color::GREEN)
.on(CursorSense::click(), move |ctx, rsc: &mut ClientRsc| {
rsc.run_event::<Submit>(add_text, (), ctx.state);
+7 -7
View File
@@ -101,15 +101,15 @@ impl Widget for Branch {
let mut top = UiRegion::FULL;
top.y.end = top.y.start.offset(40.0);
let measured = painter.place(&self.probe, top).len(Axis::X);
let px = measured.apply_rest().to_px(painter.px_len(Axis::X));
let px = measured.apply_leftover().to_px(painter.px_len(Axis::X));
let mut rest = UiRegion::FULL;
rest.y.start = rest.y.start.offset(40.0);
let mut below = UiRegion::FULL;
below.y.start = below.y.start.offset(40.0);
match px > self.threshold {
true => painter.place(&self.wide, rest),
false => painter.place(&self.narrow, rest),
true => painter.place(&self.wide, below),
false => painter.place(&self.narrow, below),
};
Size::REST
Size::LEFTOVER
}
}
@@ -172,7 +172,7 @@ impl<Rsc: UiRsc + 'static> Grow<'_, Rsc> {
fn len(&mut self) -> Option<Len> {
match self.rng.below(4) {
0 => Some(Len::px(20.0 + self.rng.below(180) as f32)),
1 => Some(Len::REST),
1 => Some(Len::LEFTOVER),
_ => None,
}
}
+11 -5
View File
@@ -14,11 +14,17 @@ impl Widget for Aligned {
.map(|(x, y)| Size { x, y }),
(Some(_), None) => painter
.known_len(&self.inner, Axis::X, UiRegion::FULL)
.map(|x| Size { x, y: Len::REST }),
.map(|x| Size {
x,
y: Len::LEFTOVER,
}),
(None, Some(_)) => painter
.known_len(&self.inner, Axis::Y, UiRegion::FULL)
.map(|y| Size { x: Len::REST, y }),
(None, None) => Some(Size::REST),
.map(|y| Size {
x: Len::LEFTOVER,
y,
}),
(None, None) => Some(Size::LEFTOVER),
};
// Drawn where it may be too big only when the aligned axes are not
// already known, then given its aligned box once its size is known.
@@ -26,8 +32,8 @@ impl Widget for Aligned {
let size = known.unwrap_or_else(|| painter.place(&self.inner, UiRegion::FULL).size());
let region = match self.align.tuple() {
(Some(x), Some(y)) => size.to_uivec2().align(RegionAlign { x, y }),
(Some(x), None) => UiRegion::new(size.x.apply_rest().align(x), UiSpan::FULL),
(None, Some(y)) => UiRegion::new(UiSpan::FULL, size.y.apply_rest().align(y)),
(Some(x), None) => UiRegion::new(size.x.apply_leftover().align(x), UiSpan::FULL),
(None, Some(y)) => UiRegion::new(UiSpan::FULL, size.y.apply_leftover().align(y)),
(None, None) => UiRegion::FULL,
};
let placed = painter.place(&self.inner, region).size();
+1 -1
View File
@@ -19,7 +19,7 @@ impl Widget for MaxSize {
fn capped(len: Len, max: Option<Len>, output: f32) -> Len {
match max {
Some(max) if len.apply_rest().to_px(output) > max.apply_rest().to_px(output) => max,
Some(max) if len.apply_leftover().to_px(output) > max.apply_leftover().to_px(output) => max,
_ => len,
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ impl Widget for Pad {
}
/// The padding is an offset from each edge, so a longer box pads the same
/// amount and the child takes the rest.
/// amount and the child takes what is left over.
fn on_resize(&self, _: Axis) -> OnResize {
OnResize::Scale
}
+1 -1
View File
@@ -21,7 +21,7 @@ impl Widget for Scroll {
let child = measured.then(|| painter.place(&self.inner, UiRegion::FULL).size());
let content_len = known_len
.unwrap_or_else(|| child.unwrap().axis(self.axis))
.apply_rest()
.apply_leftover()
.within_len(container_len)
.to_px(output_len);
self.container_len = container_len.to_px(output_len);
+2 -2
View File
@@ -9,7 +9,7 @@ pub struct SetSize {
impl Widget for SetSize {
fn draw(&mut self, painter: &mut Painter) -> Size {
// Nothing to apply: a declared length is taken where this widget is
// drawn, so the box it has already is that length, and `rest` is a
// drawn, so the box it has already is that length, and `leftover` is a
// share only whoever divides a length can work out. Both reach them
// through `size_hint`.
let child = painter.widget(&self.inner).size();
@@ -20,7 +20,7 @@ impl Widget for SetSize {
}
/// A declared axis is known without looking at the child, which is what
/// lets a span lay out around `.height(rest(1))` without drawing it.
/// lets a span lay out around `.height(leftover(1))` without drawing it.
fn size_hint(&self, axis: Axis) -> Option<Len> {
match axis {
Axis::X => self.x,
+8 -8
View File
@@ -37,9 +37,9 @@ impl Widget for Span {
for (child, len) in self.children.iter().zip(&lens) {
let mut span = UiSpan::FULL;
span.start = start;
if len.rest > 0.0 {
if len.leftover > 0.0 {
let offset = UiScalar::new(total.rel, total.px);
let rel_end = UiScalar::rel(len.rest / total.rest);
let rel_end = UiScalar::rel(len.leftover / total.leftover);
let end = (UiScalar::rel_max() + start) - offset;
start = rel_end.within(&start.to(end));
}
@@ -52,19 +52,19 @@ impl Widget for Span {
}
let used = painter.place(child, region).size().axis(!axis);
// TODO: rel shouldn't do this, but no easy way before actually calculating pixels
if used.rel > 0.0 || used.rest > 0.0 {
ortho = Len::REST;
} else if ortho.rest == 0.0 {
if used.rel > 0.0 || used.leftover > 0.0 {
ortho = Len::LEFTOVER;
} else if ortho.leftover == 0.0 {
ortho.px = ortho.px.max(used.px);
}
start.px += self.gap;
}
// Carried whole rather than collapsed to one share: a span that sizes
// from its children does not resolve `rest`, it passes the weight up,
// from its children does not resolve `leftover`, it passes the weight up,
// so nesting spans divides the same space rather than re-dividing a
// share of it. Four `rest(1)` children under two spans under one span
// get a quarter each, which collapsing to `rest(1)` per level does
// share of it. Four `leftover(1)` children under two spans under one span
// get a quarter each, which collapsing to `leftover(1)` per level does
// not give. Resolution happens at the nearest ancestor with a length,
// and the root always has one.
let along = total;
+2 -2
View File
@@ -35,11 +35,11 @@ impl Widget for Rect {
thickness: self.thickness,
inner_radius: self.inner_radius,
});
Size::REST
Size::LEFTOVER
}
fn size_hint(&self, _: Axis) -> Option<Len> {
Some(Len::REST)
Some(Len::LEFTOVER)
}
/// Its box is its primitive's own region, so a new one is written there.
+6 -6
View File
@@ -24,15 +24,15 @@ impl Widget for BranchesOnMeasurement {
let mut top = UiRegion::FULL;
top.y.end = top.y.start.offset(40.0);
let measured = painter.place(&self.probe, top).len(Axis::X);
let px = measured.apply_rest().to_px(painter.px_len(Axis::X));
let px = measured.apply_leftover().to_px(painter.px_len(Axis::X));
let mut rest = UiRegion::FULL;
rest.y.start = rest.y.start.offset(40.0);
let mut below = UiRegion::FULL;
below.y.start = below.y.start.offset(40.0);
match px > self.threshold {
true => painter.place(&self.wide, rest),
false => painter.place(&self.narrow, rest),
true => painter.place(&self.wide, below),
false => painter.place(&self.narrow, below),
};
Size::REST
Size::LEFTOVER
}
}
+7 -7
View File
@@ -131,22 +131,22 @@ fn a_moved_subtree_takes_its_children_with_it() {
fn a_fixed_length_child_keeps_it_when_the_box_around_it_grows() {
let mut h = Harness::new((400, 200));
let fixed = rect(Color::BLUE).width(50).add(&mut h.rsc);
let rest = rect(Color::GREEN).add(&mut h.rsc);
let panel = (fixed, rest).span(Dir::RIGHT).add(&mut h.rsc);
let leftover = rect(Color::GREEN).add(&mut h.rsc);
let panel = (fixed, leftover).span(Dir::RIGHT).add(&mut h.rsc);
// Changing the bar's width is the only thing that changes the box the
// panel and everything under it was drawn for.
let bar = rect(Color::RED).width(100).add(&mut h.rsc);
h.set_root((bar, panel).span(Dir::RIGHT));
assert_corners!(h, fixed, (100, 0), (150, 200));
assert_corners!(h, rest, (150, 0), (400, 200));
assert_corners!(h, leftover, (150, 0), (400, 200));
h.rsc[bar].x = Some(Len::px(200));
h.frame();
// The panel's box is 100 shorter, so the fixed child is the same 50 wide
// against its new start and the one taking the rest absorbs the change.
// against its new start and the one taking what is left absorbs the change.
assert_corners!(h, fixed, (200, 0), (250, 200));
assert_corners!(h, rest, (250, 0), (400, 200));
assert_corners!(h, leftover, (250, 0), (400, 200));
}
#[test]
@@ -187,7 +187,7 @@ fn only_a_container_that_places_its_children_lengthens_the_chain() {
);
}
/// A span that sizes from its children passes their `rest` weight up rather
/// A span that sizes from its children passes their `leftover` weight up
/// than collapsing it to one share, so nesting divides the same space instead
/// of re-dividing a share of it.
#[test]
@@ -256,7 +256,7 @@ fn hairline(h: &mut Harness, marks: &mut Vec<WidgetId>) -> StrongWidget {
fn share(h: &mut Harness, inner: StrongWidget, ratio: f32) -> StrongWidget {
SetSize {
inner,
x: Some(Len::rest(ratio)),
x: Some(Len::leftover(ratio)),
y: None,
}
.add_strong(&mut h.rsc)
+12 -12
View File
@@ -43,11 +43,11 @@ fn counted(h: &mut Harness, size: Size, dependence: OnResize) -> (WeakWidget<Cou
(id, Counts(draws))
}
/// A fixed-width leaf beside one that takes the rest, so changing the first
/// hands the second a different box without the output changing.
fn pair(h: &mut Harness, rest: OnResize) -> (WeakWidget<Counted>, Counts, WidgetId) {
/// A fixed-width leaf beside one that takes what is left over, so changing
/// the first hands the second a different box without the output changing.
fn pair(h: &mut Harness, leftover: OnResize) -> (WeakWidget<Counted>, Counts, WidgetId) {
let (first, _) = counted(h, Size::from((100, 200)), OnResize::Translate);
let (second, draws) = counted(h, Size::REST, rest);
let (second, draws) = counted(h, Size::LEFTOVER, leftover);
h.set_root((first, second).span(Dir::RIGHT));
(first, draws, second.id())
}
@@ -119,7 +119,7 @@ fn a_span_relays_out_when_a_child_it_measured_changes() {
fn a_repaint_that_keeps_its_size_does_not_relay_out() {
let mut h = Harness::new((400, 200));
let (first, draws) = counted(&mut h, Size::from((100, 200)), OnResize::Translate);
let (second, _) = counted(&mut h, Size::REST, OnResize::Translate);
let (second, _) = counted(&mut h, Size::LEFTOVER, OnResize::Translate);
h.set_root((first, second).span(Dir::RIGHT));
let settled = draws.get();
@@ -158,7 +158,7 @@ impl Widget for FromHint {
let mut region = UiRegion::FULL;
region.y.end = region.y.start.offset(len.px);
painter.widget_within(&self.inner, region);
Size::REST
Size::LEFTOVER
}
}
@@ -214,7 +214,7 @@ impl Widget for ReadsWidth {
#[test]
fn a_resize_does_not_redraw_what_the_shader_can_move() {
let mut h = Harness::new((400, 200));
let (leaf, draws) = counted(&mut h, Size::REST, OnResize::Scale);
let (leaf, draws) = counted(&mut h, Size::LEFTOVER, OnResize::Scale);
h.set_root(leaf);
let settled = draws.get();
@@ -236,7 +236,7 @@ fn a_resize_does_not_redraw_what_the_shader_can_move() {
#[test]
fn a_resize_redraws_what_does_not_scale() {
let mut h = Harness::new((400, 200));
let (leaf, draws) = counted(&mut h, Size::REST, OnResize::Redraw);
let (leaf, draws) = counted(&mut h, Size::LEFTOVER, OnResize::Redraw);
h.set_root(leaf);
let settled = draws.get();
@@ -430,8 +430,8 @@ fn a_widened_row_redraws_what_reads_its_length_and_nothing_else() {
let mut h = Harness::new((400, 200));
// What a transcript row is: something whose shaping depends on the width
// it is given, beside something that only has to be the right shape.
let (wraps, wrap_draws) = counted(&mut h, Size::REST, OnResize::Redraw);
let (backing, back_draws) = counted(&mut h, Size::REST, OnResize::Scale);
let (wraps, wrap_draws) = counted(&mut h, Size::LEFTOVER, OnResize::Redraw);
let (backing, back_draws) = counted(&mut h, Size::LEFTOVER, OnResize::Scale);
let row = (backing, wraps).span(Dir::RIGHT).add(&mut h.rsc);
let bar = rect(Color::RED).width(100).add(&mut h.rsc);
h.set_root((bar, row).span(Dir::RIGHT));
@@ -457,8 +457,8 @@ fn a_declared_length_child_is_not_redrawn_when_the_box_around_it_grows() {
// drawing the child in its own box is only an answer for that box.
let (counter, draws) = counted(&mut h, Size::from((80, 200)), OnResize::Redraw);
let fixed = counter.width(80).add(&mut h.rsc);
let (rest, _) = counted(&mut h, Size::REST, OnResize::Scale);
let row = (fixed, rest).span(Dir::RIGHT).add(&mut h.rsc);
let (leftover, _) = counted(&mut h, Size::LEFTOVER, OnResize::Scale);
let row = (fixed, leftover).span(Dir::RIGHT).add(&mut h.rsc);
let bar = rect(Color::RED).width(100).add(&mut h.rsc);
h.set_root((bar, row).span(Dir::RIGHT));
let settled = draws.get();
+2 -2
View File
@@ -327,7 +327,7 @@ fn sized(rng: &mut Rng, inner: Node) -> Node {
}
let len = |rng: &mut Rng| match rng.below(4) {
0 => Some(Len::px(20.0 + rng.below(180) as f32)),
1 => Some(Len::REST),
1 => Some(Len::LEFTOVER),
_ => None,
};
Node::Sized(len(rng), len(rng), Box::new(inner))
@@ -343,7 +343,7 @@ fn grow(rng: &mut Rng, depth: usize) -> Node {
}
let len = |rng: &mut Rng| match rng.below(4) {
0 => Some(Len::px(20.0 + rng.below(180) as f32)),
1 => Some(Len::REST),
1 => Some(Len::LEFTOVER),
2 => Some(Len::rel(0.25 + rng.below(3) as f32 * 0.25)),
_ => None,
};