Ask each child once and place its answer by re-expression
A widget draws in the box it is asked in and its answer is placed inside that box by re-expressing the drawing; nothing is drawn again in a box an answer chose. The offer machinery, whose job was to tell a measuring draw from a placing one, goes with the placing draw. A span measures each child from its cursor and moves fixed children to their slots with place_at; a share child is asked once more in its decided slot with its frame narrowed to it. A stack asks non-sizing children in the box its sizing child decided. A scroll asks its content once and moves it to the scrolled offset. A local redraw asks the retained question again and puts the answer back where the parent placed it. A symbolic length a child pinned composes through Part::Of exactly where the part is the whole box less pixels, and pins the parent's own length otherwise; dropping it let a pad reuse a drawing across a narrowed frame of the same pixel length (shrinker seeds 60, 248 and 384 at depth 5). Suite 114/114 including the two decided-box pins, fast oracle 11/11, shrinker 400 seeds at depth 5 over all fifteen cases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
4328eac756
commit
3091fb86df
12 files changed
+353
-354
No files matched your search
+32
-13
@@ -25,19 +25,23 @@ impl Widget for Span {
|
||||
// A length for every child before their final slots are chosen. The
|
||||
// frame passes through unchanged, so `rel(0.5)` is half the area this
|
||||
// span was given whatever else is in it and wherever this child sits
|
||||
// among them; what it is drawn in is the room left from the cursor,
|
||||
// because a text has to wrap at the width actually there.
|
||||
// among them; what it is asked in is the room left from the cursor,
|
||||
// because a text has to wrap at the width actually there. This is
|
||||
// the one ask a fixed child gets: its slot is its answer, and the
|
||||
// drawing is moved there once the shares are known.
|
||||
let mut cursor = Len::rel_min();
|
||||
let mut lens = Vec::with_capacity(self.children.len());
|
||||
let mut sizes = Vec::with_capacity(self.children.len());
|
||||
for child in &self.children {
|
||||
let room = Place::Within(Part::From(along(cursor, far)));
|
||||
let len = painter
|
||||
.widget_at(child, UiRegion::FULL, axis.pair(room, across))
|
||||
.len(axis);
|
||||
let size = painter
|
||||
.widget_at(child, [None; 2], axis.pair(room, across))
|
||||
.size();
|
||||
let len = size.axis(axis);
|
||||
cursor.px += len.px + self.gap;
|
||||
cursor.rel += len.rel;
|
||||
lens.push(len);
|
||||
sizes.push(size);
|
||||
}
|
||||
let lens: Vec<LayoutLen> = sizes.iter().map(|size| size.axis(axis)).collect();
|
||||
|
||||
let gaps = self
|
||||
.gap
|
||||
@@ -88,7 +92,8 @@ impl Widget for Span {
|
||||
let mut taken = Weight::ZERO;
|
||||
let mut start = Len::rel_min();
|
||||
let mut ortho = LayoutLen::ZERO;
|
||||
for (child, len) in self.children.iter().zip(&lens) {
|
||||
for (child, size) in self.children.iter().zip(&sizes) {
|
||||
let len = size.axis(axis);
|
||||
// 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
|
||||
// pixels or a fraction keeps those and overflows.
|
||||
@@ -106,12 +111,26 @@ impl Widget for Span {
|
||||
fixed.rel += len.rel;
|
||||
start = shared(fixed, taken, total.leftover, room);
|
||||
// Along the row the span says where the child goes, and that slot
|
||||
// is the drawing's box outright rather than something to place an
|
||||
// answer inside again.
|
||||
let slot = Place::Fill(Part::From(along(from, start)));
|
||||
let placed = painter.widget_at(child, UiRegion::FULL, axis.pair(slot, across));
|
||||
// is the child's box outright rather than something to place an
|
||||
// answer inside again. A share is decided here and nowhere
|
||||
// else: its slot narrows its frame, and the child is asked in
|
||||
// it, since a text wraps at the width it is actually given. A
|
||||
// fixed child's slot is its own answer, so its drawing is put
|
||||
// there as it is.
|
||||
let slot = along(from, start);
|
||||
let place = axis.pair(Place::Fill(Part::From(slot)), across);
|
||||
let used = match len.leftover > Weight::ZERO && shares {
|
||||
true => {
|
||||
let mut narrow = [None; 2];
|
||||
narrow[axis as usize] = Some(slot.len());
|
||||
painter.widget_at(child, narrow, place).len(!axis)
|
||||
}
|
||||
false => {
|
||||
painter.place_at(child, place);
|
||||
size.axis(!axis)
|
||||
}
|
||||
};
|
||||
if shrinks {
|
||||
let used = placed.len(!axis);
|
||||
// Choosing between a fixed and a relative length from the
|
||||
// span's own eventual width admits multiple fixed points.
|
||||
// A scalable child therefore makes Children scalable too;
|
||||
|
||||
Reference in new issue
Block a user