Make a declared length one that cannot carry a share
`declared_lens` filtered `leftover` out of both its sources and every consumer then re-dropped it, so the rule lived in two filters and a comment. A declaration is a `Len`: `LayoutLen::declared` states the rule once and both sources go through it, and `Declared` replaces the bare two-element array on `ActiveData` and in four signatures. The two sources stay one value deliberately. A rule decides the child's box; a hint only promises what it will report -- but `size_hint` is by contract an exact answer with no painter context, and `hints_agree` fails a widget that draws something else, so narrowing the box to a hint cannot change what is drawn. Every consumer asks about the length, never which said it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
55df32a33c
commit
2807a925af
5 files changed
+57
-34
No files matched your search
+15
-19
@@ -1,7 +1,7 @@
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
use crate::layout_diagnostics::{self as diag, Counter};
|
||||
use crate::{
|
||||
Axis, Holds, LayoutHolds, LayoutLen, Len, PlaceDesc, Px, PxVec2, RegionAlign, Rel,
|
||||
Axis, Declared, Holds, LayoutHolds, LayoutLen, Len, PlaceDesc, Px, PxVec2, RegionAlign, Rel,
|
||||
RenderedText, RetainedPrimitive, Size, StrongWidget, TextAttrs, TextBuffer, TextData,
|
||||
TextureHandle, UiRegion, UiRenderState, UiRsc, UiVec2, Weight, WidgetId, Widgets,
|
||||
render::{
|
||||
@@ -292,7 +292,7 @@ impl<'a> Painter<'a> {
|
||||
/// it resolves into its rel base. Reading them depends on nothing -- the box
|
||||
/// that comes of them is kept on the child, and `redraw` compares it
|
||||
/// there.
|
||||
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<LayoutLen>; 2] {
|
||||
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> Declared {
|
||||
self.rsc.widgets().declared_lens(id.id())
|
||||
}
|
||||
|
||||
@@ -599,11 +599,11 @@ impl Painter<'_> {
|
||||
holds: LayoutHolds,
|
||||
region: UiRegion,
|
||||
place: PlaceDesc,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
declared: Declared,
|
||||
) -> LayoutHolds {
|
||||
let mut result = LayoutHolds::ANY;
|
||||
for axis in AXES {
|
||||
let declared = declared[axis as usize];
|
||||
let declared = declared[axis];
|
||||
let holds = holds[axis];
|
||||
let result = &mut result[axis];
|
||||
// Every read became pixels against the window, so a range on
|
||||
@@ -644,13 +644,11 @@ impl Painter<'_> {
|
||||
}
|
||||
|
||||
impl Widgets {
|
||||
/// 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_lens(&self, id: WidgetId) -> [Option<LayoutLen>; 2] {
|
||||
/// What a widget's box is where a rule or its own hint says so outright.
|
||||
pub(crate) fn declared_lens(&self, id: WidgetId) -> Declared {
|
||||
let rules = self.size_rules(id);
|
||||
let widget = self.get_dyn(id);
|
||||
AXES.map(|axis| {
|
||||
Declared::per_axis(|axis| {
|
||||
rules[axis].declared().or_else(|| {
|
||||
// A hint still narrows the box where no rule does, which is
|
||||
// how a widget with a natural pixel size -- an image, a gap
|
||||
@@ -660,7 +658,7 @@ impl Widgets {
|
||||
// the box it was offered.
|
||||
widget
|
||||
.and_then(|widget| widget.size_hint(axis))
|
||||
.filter(|len| len.leftover == Weight::ZERO)
|
||||
.and_then(LayoutLen::declared)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -674,7 +672,7 @@ impl LayoutLen {
|
||||
/// the rule already gave the region its length, and the rule's length is
|
||||
/// what the widget reports there. And an axis the parent decided from
|
||||
/// the answer is the answer already.
|
||||
pub(crate) fn fills(self, declared: Option<LayoutLen>, decided: bool) -> bool {
|
||||
pub(crate) fn fills(self, declared: Option<Len>, decided: bool) -> bool {
|
||||
self.leftover != Weight::ZERO || declared.is_some() || decided
|
||||
}
|
||||
}
|
||||
@@ -693,14 +691,13 @@ impl PlaceDesc {
|
||||
self,
|
||||
region: UiRegion,
|
||||
size: Size,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
declared: Declared,
|
||||
align: RegionAlign,
|
||||
) -> UiRegion {
|
||||
let mut placed = region;
|
||||
for axis in AXES {
|
||||
let n = axis as usize;
|
||||
let reported = size[axis];
|
||||
if reported.fills(declared[n], self[axis].does_fill()) {
|
||||
if reported.fills(declared[axis], self[axis].does_fill()) {
|
||||
continue;
|
||||
}
|
||||
placed[axis] = placed[axis].place(reported.without_leftover(), align[axis]);
|
||||
@@ -722,22 +719,21 @@ impl PlaceDesc {
|
||||
self,
|
||||
own: UiRegion,
|
||||
parent_rel_base: UiVec2,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
declared: Declared,
|
||||
align: RegionAlign,
|
||||
) -> (UiVec2, UiRegion) {
|
||||
let given = self.of(own, align);
|
||||
let mut rel_base = parent_rel_base;
|
||||
let mut region = given;
|
||||
for axis in AXES {
|
||||
let n = axis as usize;
|
||||
let base = self[axis]
|
||||
.stated_rel_base()
|
||||
.unwrap_or_else(|| parent_rel_base[axis]);
|
||||
let len = declared[n]
|
||||
.map(|len| len.without_leftover().within_len(base))
|
||||
let len = declared[axis]
|
||||
.map(|len| len.within_len(base))
|
||||
.unwrap_or(base);
|
||||
rel_base[axis] = len;
|
||||
if declared[n].is_some() {
|
||||
if declared[axis].is_some() {
|
||||
region[axis] = given[axis].place(len, align[axis]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user