Retain request dependencies only when discovery supplies the answer
This commit is contained in:
1 parent
8780b40bb7
commit
0e838e9dd1
7 files changed
+183
-50
No files matched your search
+38
-18
@@ -87,29 +87,37 @@ impl<'a> Painter<'a> {
|
||||
child: &StrongWidget<W>,
|
||||
axis: Axis,
|
||||
) -> Option<RequestedLen> {
|
||||
self.request_deps.push(child.id());
|
||||
if self.rsc.widgets().size_rules(child.id())[axis].bound() == crate::Bound::ANY
|
||||
&& let Some(len) = self.size_hint(child, axis)
|
||||
{
|
||||
self.request_deps.push(child.id());
|
||||
return Some(len.into());
|
||||
}
|
||||
let rel_base = self.rel_base(axis);
|
||||
let start = self.request_deps.len();
|
||||
let mut requests = SizeRequests {
|
||||
arena: &mut self.state.requests,
|
||||
measured: None,
|
||||
widgets: self.rsc.widgets(),
|
||||
dependencies: &mut self.request_deps,
|
||||
rel_base,
|
||||
rel_base: self.rel_base[axis],
|
||||
};
|
||||
let request = requests.widget(child, axis)?;
|
||||
// An intrinsic fixed answer still draws in the offered room and is
|
||||
// moved afterwards. Only a declaration or a share chooses its ask box.
|
||||
(request.has_leftover()
|
||||
|| matches!(
|
||||
self.rsc.widgets().size_rules(child.id())[axis],
|
||||
crate::SizeRule::Request(_)
|
||||
))
|
||||
.then_some(request)
|
||||
// Intrinsic fixed content must keep its offered box for wrapping;
|
||||
// only a declaration or a share chooses the box it is drawn in.
|
||||
let request = requests.widget(child, axis).filter(|request| {
|
||||
request.has_leftover()
|
||||
|| matches!(
|
||||
self.rsc.widgets().size_rules(child.id())[axis],
|
||||
crate::SizeRule::Request(_)
|
||||
)
|
||||
});
|
||||
if request.is_some() {
|
||||
self.rel_base(axis);
|
||||
} else {
|
||||
// A discarded request contributes no dependency: the measured
|
||||
// draw below records the size and box it actually used instead.
|
||||
self.request_deps.truncate(start);
|
||||
}
|
||||
request
|
||||
}
|
||||
|
||||
/// Completes discovery after a child was measured. Only this call may use
|
||||
@@ -120,20 +128,32 @@ impl<'a> Painter<'a> {
|
||||
axis: Axis,
|
||||
len: LayoutLen,
|
||||
) -> RequestedLen {
|
||||
let rel_base = self.rel_base(axis);
|
||||
let start = self.request_deps.len();
|
||||
let bound = self.rsc.widgets().size_rules(child.id())[axis].bound();
|
||||
let mut requests = SizeRequests {
|
||||
arena: &mut self.state.requests,
|
||||
measured: Some(&self.state.active),
|
||||
widgets: self.rsc.widgets(),
|
||||
dependencies: &mut self.request_deps,
|
||||
rel_base,
|
||||
rel_base: self.rel_base[axis],
|
||||
};
|
||||
match requests.widget(child, axis) {
|
||||
Some(request) if request.linear().is_none() && request.has_leftover() => request,
|
||||
_ if len.leftover > Weight::ZERO => requests.bounded(len.into(), bound),
|
||||
_ => len.into(),
|
||||
if let Some(request) = requests.widget(child, axis)
|
||||
&& request.linear().is_none()
|
||||
&& request.has_leftover()
|
||||
{
|
||||
self.rel_base(axis);
|
||||
return request;
|
||||
}
|
||||
let request = if len.leftover > Weight::ZERO {
|
||||
requests.bounded(len.into(), bound)
|
||||
} else {
|
||||
len.into()
|
||||
};
|
||||
self.request_deps.truncate(start);
|
||||
if len.leftover > Weight::ZERO && bound != crate::Bound::ANY {
|
||||
self.rel_base(axis);
|
||||
}
|
||||
request
|
||||
}
|
||||
|
||||
/// A deferred comparison reads this window when the allocation is solved.
|
||||
|
||||
@@ -429,7 +429,7 @@ impl UiRenderState {
|
||||
// rel base is the answer wherever the ask declared a length: it was
|
||||
// resolved into the rel base when the widget was asked, and resolving
|
||||
// it again here would take the fraction of a fraction.
|
||||
let rules = rsc.widgets().size_rules(id);
|
||||
let rules = rsc.widgets().size_rules(id).clone();
|
||||
let ruled = |axis: Axis, reported: LayoutLen| {
|
||||
if matches!(rules[axis], crate::SizeRule::Request(_)) {
|
||||
return info.rel_base[axis].into();
|
||||
|
||||
@@ -128,8 +128,8 @@ impl Widgets {
|
||||
}
|
||||
|
||||
/// The length rules whoever draws this widget applies to its box.
|
||||
pub fn size_rules(&self, id: impl IdLike) -> SizeRules {
|
||||
self.data(id).unwrap().size.clone()
|
||||
pub fn size_rules(&self, id: impl IdLike) -> &SizeRules {
|
||||
&self.data(id).unwrap().size
|
||||
}
|
||||
|
||||
/// Sets one axis's rule. The widget is marked rather than its parent
|
||||
|
||||
Reference in new issue
Block a user