Say which box a pin reaches the parent through, and derive the offer
The review pass over the two commits before it: - `LayoutHolds`'s comment said a pin does not compose into the parent. It does, where the box it pinned is the parent's own box, which is the one case where the parent's own length is what was pinned. - `DrawInfo::offer` was stored beside the two fields it is computed from. It is a method now, with the open question written where it is asked rather than only in the handoff. - `Painter::own` is `frame_own` beside `extent_own`, since a widget's own box is the extent and the frame is what it is a part of. - One expression for the length a rule gives a frame (`narrowed_by`) and one for what a widget answered (`ActiveData::measured`), each of which had two. - The counter said "the placement it was pinned to" for what is now a length; the deferral in `redraw` named the seeds that made it necessary before the last commit rather than the ones that do now; three comments claimed an inset that does not exist yet. No behaviour change: 108 suite tests, 20 core, the 11 generated cases, the same two shrinker seeds failing at 400/5, and `view` and `tabs` byte-identical to the renders taken before it.
This commit is contained in:
1 parent
0954770ceb
commit
49cec82c1b
6 files changed
+76
-70
No files matched your search
+33
-36
@@ -1,9 +1,9 @@
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
||||
use crate::ui::painter::{declared_lens, frame_and_extent, part_of, placed_extent};
|
||||
use crate::ui::painter::{declared_lens, frame_and_extent, narrowed_by, part_of, placed_extent};
|
||||
use crate::{
|
||||
ActiveData, Axis, DrawLayers, Holds, IdLike, LayoutHolds, LayoutLen, Len, MaskIdx, MoveIdx,
|
||||
Moves, Painter, Part, PixelRegion, Place, PxVec2, Size, StrongWidget, UiRegion, UiRsc, Weight,
|
||||
ActiveData, Axis, DrawLayers, Holds, IdLike, LayoutHolds, LayoutLen, MaskIdx, MoveIdx, Moves,
|
||||
Painter, Part, PixelRegion, Place, PxVec2, Size, StrongWidget, UiRegion, UiRsc, Weight,
|
||||
WidgetId, Widgets,
|
||||
util::{HashMap, Vec2},
|
||||
};
|
||||
@@ -34,9 +34,6 @@ pub(super) struct DrawInfo {
|
||||
/// given at the parent's first ask of it. See [`Place`].
|
||||
pub place: [Place; 2],
|
||||
pub offer_place: [Place; 2],
|
||||
/// Whether this ask is the one the widget's answer is kept from: the
|
||||
/// first box its parent asked about, in the parent's own measuring draw.
|
||||
pub offer: bool,
|
||||
/// The frame in pixels: one multiply from the parent's own, which is
|
||||
/// where every pixel length in layout comes from.
|
||||
pub px: PxVec2,
|
||||
@@ -48,6 +45,20 @@ impl DrawInfo {
|
||||
fn fill(&self) -> [bool; 2] {
|
||||
self.place.map(Place::fills)
|
||||
}
|
||||
|
||||
/// Whether this ask is the one the widget's answer is kept from: the
|
||||
/// same widget in the place its parent measured it by, however this draw
|
||||
/// came about.
|
||||
///
|
||||
/// **Open.** A place is a length from where the asking widget's own box
|
||||
/// starts, so two drawings of that widget -- one in the box its parent
|
||||
/// measured it in, one in the box its own answer chose -- ask their
|
||||
/// children in the same places and different boxes, and this cannot tell
|
||||
/// them apart. Shrinker seeds 2 (`repaint`) and 108 (`reorder`) at depth
|
||||
/// 5 are where that shows.
|
||||
fn offer(&self) -> bool {
|
||||
self.place == self.offer_place
|
||||
}
|
||||
}
|
||||
|
||||
/// What a widget's children are placed in: its own box, the coordinates its
|
||||
@@ -153,7 +164,6 @@ impl UiRenderState {
|
||||
part: UiRegion::FULL,
|
||||
place: [Place::Within(Part::All); 2],
|
||||
offer_place: [Place::Within(Part::All); 2],
|
||||
offer: true,
|
||||
px,
|
||||
}
|
||||
}
|
||||
@@ -209,9 +219,7 @@ impl UiRenderState {
|
||||
/// The root's frame: the window, narrowed by the root's own rules. Its
|
||||
/// extent is that frame, since nothing above it chose anything else.
|
||||
fn root_region(id: WidgetId, widgets: &Widgets) -> UiRegion {
|
||||
let declared = declared_lens(widgets, id);
|
||||
let narrow =
|
||||
AXES.map(|axis| declared[axis as usize].map(|len| Len::from_parts(len.rel, len.px)));
|
||||
let narrow = narrowed_by(declared_lens(widgets, id), UiRegion::FULL);
|
||||
frame_and_extent(
|
||||
UiRegion::FULL,
|
||||
UiRegion::FULL,
|
||||
@@ -257,13 +265,13 @@ impl UiRenderState {
|
||||
// axis the parent left open. The frame itself does not change, so
|
||||
// nothing under it resolves a fraction a second time.
|
||||
//
|
||||
// From the answer it gave when its parent first asked, and not from
|
||||
// what a placing evaluation reported: a drawing made in the box that
|
||||
// answer chose is answering a different question, and placing it by
|
||||
// that would move the box out from under itself.
|
||||
let measured = match info.offer {
|
||||
// From the answer it gave when its parent measured it, and not from
|
||||
// what a placing evaluation reported: placing a drawing by what it
|
||||
// said in the box its own answer chose would move the box out from
|
||||
// under it.
|
||||
let measured = match info.offer() {
|
||||
true => answer.0,
|
||||
false => self.active[&id].answer.map_or(answer.0, |(size, _)| size),
|
||||
false => self.active[&id].measured().unwrap_or(answer.0),
|
||||
};
|
||||
let extent = placed_extent(
|
||||
part,
|
||||
@@ -295,7 +303,7 @@ impl UiRenderState {
|
||||
// the same question again from these.
|
||||
active.frame_abs = frame;
|
||||
active.frame = info.frame;
|
||||
if info.offer {
|
||||
if info.offer() {
|
||||
active.answer = Some(answer);
|
||||
active.offer_place = info.offer_place;
|
||||
active.offer_part = part;
|
||||
@@ -361,7 +369,7 @@ impl UiRenderState {
|
||||
// Only evaluation at the original offer establishes the children's
|
||||
// offers. A placing evaluation must not overwrite that question.
|
||||
let px = info.px;
|
||||
let at_offer = info.offer;
|
||||
let at_offer = info.offer();
|
||||
|
||||
let mut painter = Painter {
|
||||
state: self,
|
||||
@@ -380,7 +388,7 @@ impl UiRenderState {
|
||||
offered: Vec::new(),
|
||||
at_offer,
|
||||
size_deps: Vec::new(),
|
||||
own: [Holds::ANY; 2],
|
||||
frame_own: [Holds::ANY; 2],
|
||||
under: LayoutHolds::ANY,
|
||||
extent_own: [Holds::ANY; 2],
|
||||
answer_under: LayoutHolds::ANY,
|
||||
@@ -417,7 +425,7 @@ impl UiRenderState {
|
||||
offered: _,
|
||||
at_offer: _,
|
||||
size_deps,
|
||||
own,
|
||||
frame_own,
|
||||
under,
|
||||
move_idx,
|
||||
layer,
|
||||
@@ -458,7 +466,7 @@ impl UiRenderState {
|
||||
self.moves.remove(idx);
|
||||
}
|
||||
let own_holds = LayoutHolds {
|
||||
frame: own,
|
||||
frame: frame_own,
|
||||
extent: extent_own,
|
||||
extent_len,
|
||||
};
|
||||
@@ -488,7 +496,6 @@ impl UiRenderState {
|
||||
part: UiRegion::FULL,
|
||||
place: [Place::Within(Part::All); 2],
|
||||
offer_place: [Place::Within(Part::All); 2],
|
||||
offer: false,
|
||||
px,
|
||||
},
|
||||
rsc,
|
||||
@@ -659,7 +666,7 @@ impl UiRenderState {
|
||||
for axis in AXES {
|
||||
let n = axis as usize;
|
||||
if holds.extent_len[n].is_some_and(|pinned| pinned != extent.axis(axis).len()) {
|
||||
diag::bump(Counter::OutsidePlacement);
|
||||
diag::bump(Counter::OutsidePinnedLen);
|
||||
}
|
||||
if !holds.frame[n].contains(info.px.axis(axis)) {
|
||||
diag::bump(Counter::OutsideFrame);
|
||||
@@ -721,13 +728,9 @@ impl UiRenderState {
|
||||
fn place_child(&mut self, child: WidgetId, at: &Placing, rsc: &mut dyn UiRsc) {
|
||||
let active = &self.active[&child];
|
||||
let (frame, part) = Self::re_ask(active, at.extent, active.place);
|
||||
// The answer it gave, and not what its last drawing reported: a
|
||||
// drawing made in the box that answer chose is answering a different
|
||||
// question.
|
||||
let answer = active.answer.map_or(active.size, |(size, _)| size);
|
||||
let extent = placed_extent(
|
||||
part,
|
||||
answer,
|
||||
active.measured().unwrap_or(active.size),
|
||||
active.declared,
|
||||
active.place.map(Place::fills),
|
||||
active.own_align,
|
||||
@@ -744,10 +747,6 @@ impl UiRenderState {
|
||||
part,
|
||||
place: active.place,
|
||||
offer_place: active.offer_place,
|
||||
// Putting it back where it was asked about is that ask again, so
|
||||
// what it answers there is the answer -- and putting it anywhere
|
||||
// else is not, however the box was arrived at.
|
||||
offer: active.place == active.offer_place,
|
||||
px: frame.size().to_px(at.px),
|
||||
};
|
||||
self.place(child, extent, info, rsc);
|
||||
@@ -1197,7 +1196,6 @@ impl UiRenderState {
|
||||
part: Self::re_ask(active, parent_extent, active.place).1,
|
||||
place: active.place,
|
||||
offer_place: active.offer_place,
|
||||
offer: false,
|
||||
px,
|
||||
};
|
||||
// The ask that measured it, asked again: the box it was measured in
|
||||
@@ -1207,7 +1205,6 @@ impl UiRenderState {
|
||||
let offered = DrawInfo {
|
||||
place: info.offer_place,
|
||||
part: active.offer_part,
|
||||
offer: true,
|
||||
..info
|
||||
};
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
@@ -1224,8 +1221,8 @@ impl UiRenderState {
|
||||
// the drawing goes in alone. Removing it -- asking the measuring
|
||||
// question here and placing the answer afterwards -- is what the
|
||||
// transparent-frames plan asks for next, and it does not hold yet:
|
||||
// seeds 104 (align) and 210 (reorder) at depth 5 settle differently
|
||||
// warm and cold without it.
|
||||
// seeds 104 (`align`) and 210 (`reorder`) at depth 5 settle
|
||||
// differently warm and cold without it.
|
||||
if info.part.size() != offered.part.size() {
|
||||
self.mark(id, rsc.widgets_mut());
|
||||
self.mark(parent, rsc.widgets_mut());
|
||||
|
||||
Reference in new issue
Block a user