Replace placement calls with region nodes

This commit is contained in:
iris-ai committed 2026-09-15 18:02:28 -04:00
1 parent f437495309
commit 71c9c39523
23 files changed
+374 -170

No files matched your search

+3 -2
View File
@@ -29,14 +29,15 @@ impl Widget for Aligned {
// 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.
let had_size = known.is_some();
let size = known.unwrap_or_else(|| painter.place(&self.inner, UiRegion::FULL).size());
let size =
known.unwrap_or_else(|| painter.widget_within(&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_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();
let placed = painter.widget_within(&self.inner, region).size();
if had_size { placed } else { size }
}
}
+3 -3
View File
@@ -13,12 +13,12 @@ impl Widget for Scroll {
fn draw(&mut self, painter: &mut Painter) -> Size {
let container_len = painter.px_len(self.axis);
// Draw in the whole container only when its scrolling-axis length is
// not already known, then place it at the scrolled offset.
// not already known, then draw it at the scrolled offset.
let (answer_len, measured) = match painter.known_len(&self.inner, self.axis, UiRegion::FULL)
{
Some(len) => (len, None),
None => {
let size = painter.place(&self.inner, UiRegion::FULL).size();
let size = painter.widget_within(&self.inner, UiRegion::FULL).size();
(size.axis(self.axis), Some(size))
}
};
@@ -43,7 +43,7 @@ impl Widget for Scroll {
let mut region = UiRegion::FULL.offset(Vec2::from_axis(self.axis, -self.amt, 0.0));
region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len);
let placed = painter.place(&self.inner, region).size();
let placed = painter.widget_within(&self.inner, region).size();
measured.unwrap_or_else(|| Size::from_axis(self.axis, answer_len, placed.axis(!self.axis)))
}
}
+16 -12
View File
@@ -21,8 +21,8 @@ pub struct Span {
impl Widget for Span {
fn draw(&mut self, painter: &mut Painter) -> Size {
let axis = self.dir.axis;
// A length for every child before any is placed: from its own hint
// where it has one, and from drawing it where it does not.
// A length for every child before their final boxes are chosen: from
// a hint where one exists, and from drawing otherwise.
let mut cursor = UiScalar::rel_min();
let mut lens = Vec::with_capacity(self.children.len());
for child in &self.children {
@@ -33,7 +33,7 @@ impl Widget for Span {
let region = UiRegion::from_axis(axis, span, UiSpan::FULL);
let len = match painter.known_len(child, axis, region) {
Some(len) => len,
None => painter.place(child, region).len(axis),
None => painter.widget_within(child, region).len(axis),
};
cursor.px += len.px + self.gap;
cursor.rel += len.rel;
@@ -47,24 +47,28 @@ impl Widget for Span {
// beside 300 px is full at 600 and overfull at 400. The answer is
// the same on either side of the length the fixed parts alone fill.
let fixed = 1.0 - total.rel;
let shares = total.leftover > 0.0 && fixed * painter.px_len(axis) > total.px;
let mut shares = false;
if total.leftover > 0.0 {
let range = if fixed > 0.0 {
let current = painter.px_len(axis);
let holds = if fixed > 0.0 {
let full = total.px / fixed;
shares = current > full;
match shares {
true => full..=f32::INFINITY,
false => f32::NEG_INFINITY..=full,
true => Holds::exact(full.next_up()..=f32::INFINITY),
false => Holds::exact(f32::NEG_INFINITY..=full),
}
} else if fixed < 0.0 {
let full = total.px / fixed;
shares = current < full;
match shares {
true => f32::NEG_INFINITY..=full,
false => full..=f32::INFINITY,
true => Holds::exact(f32::NEG_INFINITY..=full.next_down()),
false => Holds::exact(full..=f32::INFINITY),
}
} else {
f32::NEG_INFINITY..=f32::INFINITY
shares = total.px < 0.0;
Holds::ANY
};
painter.holds(axis, range);
painter.holds(axis, holds);
}
let mut start = UiScalar::rel_min();
@@ -93,7 +97,7 @@ impl Widget for Span {
if self.dir.sign == Sign::Neg {
region.flip(axis);
}
let placed = painter.place(child, region);
let placed = painter.widget_within(child, region);
if self.ortho == OrthoSize::Children {
let used = placed.len(!axis);
// Choosing between a fixed and a relative length from the
+11 -1
View File
@@ -31,6 +31,14 @@ widget_trait! {
}
}
fn region_node(self) -> impl WidgetIdFn<Rsc, WL::Widget> {
|state| {
let id = self.add(state);
state.ui_mut().widgets.set_region_node(id, true);
id
}
}
fn sized(self, size: impl Into<Size>) -> impl WidgetFn<Rsc, SetSize> {
let size = size.into();
move |state| SetSize {
@@ -85,7 +93,9 @@ widget_trait! {
fn scrollable(self) -> impl WidgetIdFn<Rsc, Scroll> where Rsc: HasEvents {
move |state| {
Scroll::new(self.add_strong(state), Axis::Y)
let inner = self.add(state);
state.ui_mut().widgets.set_region_node(inner, true);
Scroll::new(inner.upgrade(state), Axis::Y)
.on(CursorSense::Scroll, |ctx, rsc| {
let delta = ctx.data.scroll_delta.y * 50.0;
ctx.widget(rsc).scroll(delta);