One argument says where a child goes and what its fractions are of
`Place` was a product written as a sum -- a `Part` and a fill flag -- and `Part` named three operations the geometry already had, under words that did not match them. `Of` was `UiSpan::within`, `From` was `UiSpan::shift`, and `Sized` was `placement`'s own body with the length given rather than reported. Both enums are gone. `PlaceDescAxis` says one axis, named after the operation it performs: `within`, `shifted`, `sized`, and `WHOLE`. What is optional is a builder -- `fills` and `rel_base` -- so a caller writes only what it decided, and the rel base it does not write follows the constructor: a span composed into the caller's box narrows it, a span along a cursor does not, a decided length is it. That was the one rule a caller could get wrong with nothing failing. `PlaceDesc` says both axes with named fields, so `axis`, `axis_mut` and `from_axis` work the way they do on every other pair here, and the joint work -- resolving a region, reading the fill flags -- is written once rather than per axis. `widget_at` and `place_at` take `impl Into<PlaceDesc>`, so a wrapper passes a `UiRegion` and says nothing else. `widget_within` and `ActiveData::narrow_rel_base` are deleted; `asked` and `placed` carry the rel base their ask stated. Cold layout is byte-identical to `84dad21`.
This commit is contained in:
1 parent
c55be21761
commit
58ce74dd7d
12 files changed
+367
-271
No files matched your search
+8
-13
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
LayerId, LayoutHolds, LayoutLen, Len, MaskIdx, MoveIdx, Place, RegionAlign, RetainedPrimitive,
|
||||
LayerId, LayoutHolds, LayoutLen, MaskIdx, MoveIdx, PlaceDesc, RegionAlign, RetainedPrimitive,
|
||||
Size, TextureHandle, UiRegion, UiVec2, WidgetId,
|
||||
};
|
||||
|
||||
@@ -14,18 +14,13 @@ pub struct ActiveData {
|
||||
/// What a fraction declared or reported under this widget is a fraction
|
||||
/// of, as a length of the window.
|
||||
pub rel_base: UiVec2,
|
||||
/// A rel base its parent decided for it on each axis -- a row's slot, or
|
||||
/// padding's rel base less its pixels -- as a length of the window. `None`
|
||||
/// forwards the parent's rel base. What it declared is kept separately in
|
||||
/// `declared` and is a fraction of whichever of the two reached it.
|
||||
pub narrow_rel_base: [Option<Len>; 2],
|
||||
/// Where its drawing was put, and where it was asked, each as a part of
|
||||
/// its parent's box. The two differ where a container asks in one place
|
||||
/// and puts the answer in another -- a row measures from its cursor and
|
||||
/// puts the child in its slot. A part is a length from the box's start,
|
||||
/// so a box that moved re-places every child by re-adding that start.
|
||||
pub placed: [Place; 2],
|
||||
pub asked: [Place; 2],
|
||||
/// Where its drawing was put, and where it was asked. The two differ
|
||||
/// where a container asks in one place and puts the answer in another --
|
||||
/// a row measures from its cursor and puts the child in its slot. Each
|
||||
/// carries the rel base that ask stated, so asking again from either is
|
||||
/// the same question it was.
|
||||
pub placed: PlaceDesc,
|
||||
pub asked: PlaceDesc,
|
||||
/// The box it was asked in, in the parent's region-node coordinates: the
|
||||
/// box its drawing was made in and the one its contract is about. Its
|
||||
/// drawing is placed elsewhere by re-expression, never by asking again.
|
||||
|
||||
+57
-100
@@ -1,7 +1,7 @@
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
use crate::layout_diagnostics::{self as diag, Counter};
|
||||
use crate::{
|
||||
Axis, Holds, LayoutHolds, LayoutLen, Len, Part, Place, Px, PxVec2, RegionAlign, Rel,
|
||||
Axis, Holds, LayoutHolds, LayoutLen, Len, PlaceDesc, Px, PxVec2, RegionAlign, Rel,
|
||||
RenderedText, RetainedPrimitive, Size, StrongWidget, TextAttrs, TextBuffer, TextData,
|
||||
TextureHandle, UiRegion, UiRenderState, UiRsc, UiSpan, UiVec2, Weight, WidgetId, Widgets,
|
||||
render::{
|
||||
@@ -144,68 +144,49 @@ impl<'a> Painter<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
/// Draws a widget in the whole of this widget's own box, with the rel base
|
||||
/// forwarded unchanged: what a container that is only a wrapper around
|
||||
/// one child wants, and what every transparent container passes for the
|
||||
/// rel base.
|
||||
/// Draws a widget in the whole of this widget's own box, with the rel
|
||||
/// base forwarded unchanged: what a container that is only a wrapper
|
||||
/// around one child wants.
|
||||
pub fn widget<'s, W: ?Sized>(&'s mut self, id: &'s StrongWidget<W>) -> DrawResult<'s, 'a, W> {
|
||||
self.widget_within(id, UiRegion::FULL)
|
||||
self.widget_at(id, UiRegion::FULL)
|
||||
}
|
||||
|
||||
/// Draws a widget in `region` of this widget's own box, in that box's own
|
||||
/// coordinates -- an inset, or an offset.
|
||||
///
|
||||
/// The child's rel base is this widget's narrowed the same way the box is,
|
||||
/// so padding takes its pixels off both and an offset, which changes the
|
||||
/// box's length by nothing, changes neither. An axis the region leaves
|
||||
/// whole is not read at all, so a wrapper that only moves its child does
|
||||
/// not pin the drawing to a rel base.
|
||||
pub fn widget_within<'s, W: ?Sized>(
|
||||
&'s mut self,
|
||||
id: &'s StrongWidget<W>,
|
||||
region: UiRegion,
|
||||
) -> DrawResult<'s, 'a, W> {
|
||||
let narrow = AXES.map(|axis| {
|
||||
let len = region.axis(axis).len();
|
||||
(len != Len::FULL).then(|| len.within_len(self.rel_base(axis)))
|
||||
});
|
||||
self.widget_at(id, region_places(region), narrow)
|
||||
/// Resolves what the place says about the child's rel base into a length,
|
||||
/// where that is this widget's own narrowed the way the region is. An
|
||||
/// axis the region leaves whole is not read at all, so a wrapper that
|
||||
/// only moves its child does not pin its drawing to a rel base.
|
||||
fn state_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
|
||||
for axis in AXES {
|
||||
if let Some(span) = place.axis(axis).narrows_rel_base() {
|
||||
let len = span.len();
|
||||
let stated = (len != Len::FULL).then(|| len.within_len(self.rel_base(axis)));
|
||||
*place.axis_mut(axis) = place.axis(axis).with_rel_base(stated);
|
||||
}
|
||||
}
|
||||
place
|
||||
}
|
||||
|
||||
/// Asks a child, saying what its fractions are of and where it is asked.
|
||||
///
|
||||
/// `place` is the child's region, per axis, said as a part of this
|
||||
/// widget's own: see [`Place`]. The child draws once, in that region,
|
||||
/// and its answer is placed inside it by re-expressing the drawing.
|
||||
/// Nothing is drawn again in a box an answer chose; a container that
|
||||
/// puts the answer somewhere else says so with [`Self::place_at`].
|
||||
/// `place` says where the child goes and what its fractions are of:
|
||||
/// see [`PlaceDesc`]. A `UiRegion` converts into the common case, which
|
||||
/// is a box of this widget's own with the answer placed inside it.
|
||||
///
|
||||
/// `narrow_rel_base` is the child's rel base, per axis, as a length of
|
||||
/// the window: a resolved share, or a box a sibling's answer decided.
|
||||
/// `None`, whole or per axis, forwards this widget's own -- which is
|
||||
/// what a container that only divides room passes, so a fraction under
|
||||
/// it means the same wherever it sits and however deeply it is nested.
|
||||
/// It only ever narrows: a length the child declares narrows it again
|
||||
/// here whatever the caller says, and what comes of it also narrows the
|
||||
/// region, placed in the part by the child's alignment.
|
||||
/// The child draws once, in the region that comes of it, and its answer
|
||||
/// is placed inside that region by re-expressing the drawing. Nothing is
|
||||
/// drawn again in a box an answer chose; a container that puts the
|
||||
/// answer somewhere else says so with [`Self::place_at`].
|
||||
pub fn widget_at<'s, W: ?Sized>(
|
||||
&'s mut self,
|
||||
id: &'s StrongWidget<W>,
|
||||
place: [Place; 2],
|
||||
narrow_rel_base: impl Into<Option<[Option<Len>; 2]>>,
|
||||
place: impl Into<PlaceDesc>,
|
||||
) -> DrawResult<'s, 'a, W> {
|
||||
let narrow_rel_base = narrow_rel_base.into().unwrap_or([None; 2]);
|
||||
let place = self.state_rel_base(place.into());
|
||||
let region_node = self.rsc.widgets().is_region_node(id.id());
|
||||
let declared = self.declared_lens(id);
|
||||
let align = self.rsc.widgets().alignment(id.id());
|
||||
let (rel_base, region) = rel_base_and_region(
|
||||
self.region,
|
||||
self.rel_base,
|
||||
place,
|
||||
narrow_rel_base,
|
||||
declared,
|
||||
align,
|
||||
);
|
||||
let (rel_base, region) =
|
||||
rel_base_and_region(self.region, self.rel_base, place, declared, align);
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
if region_node {
|
||||
diag::bump(Counter::RegionNodeDraws);
|
||||
@@ -230,15 +211,14 @@ impl<'a> Painter<'a> {
|
||||
region,
|
||||
placed: place,
|
||||
asked: place,
|
||||
narrow_rel_base,
|
||||
re_asked,
|
||||
px,
|
||||
},
|
||||
None,
|
||||
self.rsc,
|
||||
);
|
||||
let holds = self.in_parent(holds, region, place, narrow_rel_base, declared);
|
||||
let answer_holds = self.in_parent(answer_holds, region, place, narrow_rel_base, declared);
|
||||
let holds = self.in_parent(holds, region, place, declared);
|
||||
let answer_holds = self.in_parent(answer_holds, region, place, declared);
|
||||
match self.under.iter_mut().find(|(child, _)| *child == id.id()) {
|
||||
Some((_, kept)) => *kept = holds,
|
||||
None => self.under.push((id.id(), holds)),
|
||||
@@ -273,12 +253,14 @@ impl<'a> Painter<'a> {
|
||||
pub fn place_at<'s, W: ?Sized>(
|
||||
&'s mut self,
|
||||
id: &'s StrongWidget<W>,
|
||||
place: [Place; 2],
|
||||
narrow_rel_base: impl Into<Option<[Option<Len>; 2]>>,
|
||||
place: impl Into<PlaceDesc>,
|
||||
) -> DrawResult<'s, 'a, W> {
|
||||
let narrow_rel_base = narrow_rel_base.into().unwrap_or([None; 2]);
|
||||
if narrow_rel_base.iter().any(Option::is_some) || !self.children.contains(&id.id()) {
|
||||
return self.widget_at(id, place, narrow_rel_base);
|
||||
let place = self.state_rel_base(place.into());
|
||||
let states_rel_base = AXES
|
||||
.iter()
|
||||
.any(|&axis| place.axis(axis).stated_rel_base().is_some());
|
||||
if states_rel_base || !self.children.contains(&id.id()) {
|
||||
return self.widget_at(id, place);
|
||||
}
|
||||
let at = self.placing();
|
||||
self.state.place_in(id.id(), &at, place, self.rsc);
|
||||
@@ -619,8 +601,7 @@ impl Painter<'_> {
|
||||
&self,
|
||||
holds: LayoutHolds,
|
||||
region: UiRegion,
|
||||
place: [Place; 2],
|
||||
narrow_rel_base: [Option<Len>; 2],
|
||||
place: PlaceDesc,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
) -> LayoutHolds {
|
||||
let mut result = LayoutHolds::ANY;
|
||||
@@ -629,11 +610,12 @@ impl Painter<'_> {
|
||||
// Every read became pixels against the window, so a range on
|
||||
// it is already in this widget's terms.
|
||||
result.window[n] = holds.window[n];
|
||||
let reaches = narrow_rel_base[n].is_none()
|
||||
&& !matches!(place[n].part(), Part::Sized(_))
|
||||
let at = *place.axis(axis);
|
||||
let reaches = at.stated_rel_base().is_none()
|
||||
&& !at.is_sized()
|
||||
&& declared[n].is_none_or(|len| len.rel != Rel::ZERO);
|
||||
result.rel_base[n] = holds.rel_base[n].and(reaches.then(|| self.rel_base.axis(axis)));
|
||||
match (place[n].part(), declared[n].is_some()) {
|
||||
match (at.within_span(), declared[n].is_some()) {
|
||||
// Its box is a part of this widget's own box, in that box's
|
||||
// own lengths, so what it holds for maps back through that
|
||||
// part into a range on this widget's box. A length it pinned
|
||||
@@ -641,7 +623,7 @@ impl Painter<'_> {
|
||||
// part is the whole of the box less pixels, which is the one
|
||||
// shape that inverts exactly; any other part pins this
|
||||
// widget's own length.
|
||||
(Part::Of(span), false) => {
|
||||
(Some(span), false) => {
|
||||
let part_len = span.len();
|
||||
result.region[n] = holds.region[n].through(part_len);
|
||||
result.region_len[n] = holds.region_len[n].map(|pinned| match part_len.rel {
|
||||
@@ -663,14 +645,6 @@ impl Painter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A box of a widget's own, per axis, with the answer placed inside it.
|
||||
fn region_places(region: UiRegion) -> [Place; 2] {
|
||||
[
|
||||
Place::Within(Part::Of(region.x)),
|
||||
Place::Within(Part::Of(region.y)),
|
||||
]
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@@ -715,14 +689,14 @@ pub(crate) fn placement(
|
||||
region: UiRegion,
|
||||
size: Size,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
fill: [bool; 2],
|
||||
place: PlaceDesc,
|
||||
align: RegionAlign,
|
||||
) -> UiRegion {
|
||||
let mut placed = region;
|
||||
for axis in AXES {
|
||||
let n = axis as usize;
|
||||
let reported = size.axis(axis);
|
||||
if fills(reported, declared[n], fill[n]) {
|
||||
if fills(reported, declared[n], place.axis(axis).does_fill()) {
|
||||
continue;
|
||||
}
|
||||
let len = Len::from_parts(reported.rel, reported.px);
|
||||
@@ -737,32 +711,27 @@ pub(crate) fn placement(
|
||||
/// widget asking draws in.
|
||||
///
|
||||
/// `own` is that widget's own box, and `place` what of it the child is
|
||||
/// given. `narrow_rel_base` is a rel base the container decided for the child -- a row's
|
||||
/// slot, or padding's rel base less its pixels -- and [`Part::Sized`] one a
|
||||
/// sibling's answer decided; both are window lengths, like every other
|
||||
/// length here, since a slot of a row is not a fraction of anything the row
|
||||
/// can name. The child's declaration is a fraction of whichever reached it,
|
||||
/// and is the only one of the three that also places the box: a box the
|
||||
/// caller decided is what `place` names.
|
||||
/// given, including any rel base it states -- a row's slot, or padding's rel
|
||||
/// base less its pixels. That is a window length, like every other length
|
||||
/// here, since a slot of a row is not a fraction of anything the row can
|
||||
/// name. The child's declaration is a fraction of whichever reached it, and
|
||||
/// is the only one that also places the box: a box the caller decided is
|
||||
/// what `place` names.
|
||||
pub(crate) fn rel_base_and_region(
|
||||
own: UiRegion,
|
||||
parent_rel_base: UiVec2,
|
||||
place: [Place; 2],
|
||||
narrow_rel_base: [Option<Len>; 2],
|
||||
place: PlaceDesc,
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
align: RegionAlign,
|
||||
) -> (UiVec2, UiRegion) {
|
||||
let given = region_of(own, place, align);
|
||||
let given = place.of(own, align);
|
||||
let mut rel_base = parent_rel_base;
|
||||
let mut region = given;
|
||||
for axis in AXES {
|
||||
let n = axis as usize;
|
||||
let sized = match place[n].part() {
|
||||
Part::Sized(len) => Some(len),
|
||||
_ => None,
|
||||
};
|
||||
let base = sized
|
||||
.or(narrow_rel_base[n])
|
||||
let base = place
|
||||
.axis(axis)
|
||||
.stated_rel_base()
|
||||
.unwrap_or_else(|| parent_rel_base.axis(axis));
|
||||
let len = declared[n]
|
||||
.map(|len| Len::from_parts(len.rel, len.px).within_len(base))
|
||||
@@ -776,15 +745,3 @@ pub(crate) fn rel_base_and_region(
|
||||
}
|
||||
(rel_base, region)
|
||||
}
|
||||
|
||||
/// The part of a widget's own box a `place` names, in the coordinates that
|
||||
/// box is in.
|
||||
fn region_of(own: UiRegion, place: [Place; 2], align: RegionAlign) -> UiRegion {
|
||||
let mut region = own;
|
||||
for axis in AXES {
|
||||
*region.axis_mut(axis) = place[axis as usize]
|
||||
.part()
|
||||
.of(*own.axis(axis), align.axis(axis));
|
||||
}
|
||||
region
|
||||
}
|
||||
+222
-50
@@ -1,70 +1,242 @@
|
||||
use crate::{AxisAlign, Len, PrimitiveHandle, UiRegion, UiSpan};
|
||||
use crate::{Axis, AxisAlign, Len, PrimitiveHandle, RegionAlign, UiRegion, UiSpan};
|
||||
|
||||
/// A child's region along one axis, said as a part of the region the widget
|
||||
/// saying it was given.
|
||||
/// How a child's region along one axis comes from the region of the widget
|
||||
/// asking, and what its fractions are of.
|
||||
///
|
||||
/// The three ways of saying a region are the three the geometry already has:
|
||||
/// a span composed into the caller's box, a span shifted to where that box
|
||||
/// starts, and a length placed in it by alignment. Which one is meant cannot
|
||||
/// be read off the numbers, since two of them take the same span and apply
|
||||
/// it differently, so it is said here.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Part {
|
||||
/// Window lengths from where the box starts, which is what a container
|
||||
/// dividing room among its children speaks: a child's report is a window
|
||||
/// length, so the cursor that sums those reports is one too. A moved box
|
||||
/// re-places every child by re-adding its start, exactly. A fraction
|
||||
/// here is a fraction of the window and not of the box -- the whole of a
|
||||
/// box is [`Self::WHOLE`], not a `rel(1.0)` span.
|
||||
From(UiSpan),
|
||||
/// A part of the box in its own coordinates, which is what a container
|
||||
/// that insets one speaks: taking eleven pixels off the end needs no
|
||||
/// length, where saying the same thing in window lengths would make the
|
||||
/// container read its own box -- and a box chosen from its own answer
|
||||
/// then feeds back into the answer.
|
||||
Of(UiSpan),
|
||||
/// A box of this length, wherever in the parent's box the child's own
|
||||
/// alignment puts it, and that same length as its rel base. Unlike `From`,
|
||||
/// it is a length decided from above rather than a place along a
|
||||
/// container's cursor -- what a stack's sizing child decides for the
|
||||
/// rest.
|
||||
pub struct PlaceDescAxis {
|
||||
span: PlaceSpan,
|
||||
fills: bool,
|
||||
rel_base: RelBase,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum PlaceSpan {
|
||||
Within(UiSpan),
|
||||
Shifted(UiSpan),
|
||||
Sized(Len),
|
||||
}
|
||||
|
||||
impl Part {
|
||||
/// The whole of the box. Not a variant of its own: it composes and
|
||||
/// inverts through the same expressions every other `Of` does.
|
||||
pub const WHOLE: Self = Self::Of(UiSpan::FULL);
|
||||
/// What a child's fractions are of, where the caller has not named a length.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum RelBase {
|
||||
/// The caller's own, unchanged.
|
||||
Inherit,
|
||||
/// The caller's own, narrowed the way the region is.
|
||||
WithRegion,
|
||||
/// This length of the window.
|
||||
Len(Len),
|
||||
}
|
||||
|
||||
impl PlaceDescAxis {
|
||||
/// The whole of the caller's box.
|
||||
pub const WHOLE: Self = Self::within(UiSpan::FULL);
|
||||
|
||||
/// `span` composed into the caller's own box, so it moves and scales
|
||||
/// with it: [`UiSpan::within`], which is what a container that insets
|
||||
/// one speaks. Taking eleven pixels off the end needs no length, where
|
||||
/// saying the same thing in window lengths would make the container read
|
||||
/// its own box -- and a box chosen from its own answer then feeds back
|
||||
/// into the answer.
|
||||
///
|
||||
/// The child's rel base is narrowed the same way, so padding takes its
|
||||
/// pixels off both and `rel(1)` under it fills the caller rather than
|
||||
/// overflowing it.
|
||||
pub const fn within(span: UiSpan) -> Self {
|
||||
Self {
|
||||
span: PlaceSpan::Within(span),
|
||||
fills: false,
|
||||
rel_base: RelBase::WithRegion,
|
||||
}
|
||||
}
|
||||
|
||||
/// `span` shifted to where the caller's own box starts: window lengths
|
||||
/// along a cursor, which is what a container dividing room among its
|
||||
/// children speaks. A child's report is a window length, so the cursor
|
||||
/// that sums those reports is one too, and a moved box re-places every
|
||||
/// child by re-adding its start, exactly.
|
||||
///
|
||||
/// The child's rel base passes through: how far along the cursor a child
|
||||
/// sits says nothing about what a fraction under it is of.
|
||||
pub const fn shifted(span: UiSpan) -> Self {
|
||||
Self {
|
||||
span: PlaceSpan::Shifted(span),
|
||||
fills: false,
|
||||
rel_base: RelBase::Inherit,
|
||||
}
|
||||
}
|
||||
|
||||
/// A box this long, placed in the caller's own by the child's alignment:
|
||||
/// the rule that places an answer, with the length given from above
|
||||
/// rather than reported. What a stack's sizing child decides for the
|
||||
/// rest. It is the child's rel base too.
|
||||
pub const fn sized(len: Len) -> Self {
|
||||
Self {
|
||||
span: PlaceSpan::Sized(len),
|
||||
fills: false,
|
||||
rel_base: RelBase::Len(len),
|
||||
}
|
||||
}
|
||||
|
||||
/// This region is the child's placement: its answer is not placed inside
|
||||
/// it again. A container uses it where it hands back exactly what the
|
||||
/// child asked for -- a row placing a child at the length it reported.
|
||||
pub const fn fills(mut self) -> Self {
|
||||
self.fills = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// What the child's fractions are of, as a length of the window: a
|
||||
/// resolved share, or a box a sibling's answer decided.
|
||||
pub const fn rel_base(mut self, len: Len) -> Self {
|
||||
self.rel_base = RelBase::Len(len);
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether the region is the placement outright, rather than a box the
|
||||
/// answer is placed inside.
|
||||
pub(crate) const fn does_fill(self) -> bool {
|
||||
self.fills
|
||||
}
|
||||
|
||||
/// Where it lands in the coordinates `own` is in.
|
||||
pub(crate) fn of(self, own: UiSpan, align: AxisAlign) -> UiSpan {
|
||||
match self {
|
||||
Self::From(span) => UiSpan::new(own.start + span.start, own.start + span.end),
|
||||
Self::Of(span) => span.within(&own),
|
||||
Self::Sized(len) => {
|
||||
match self.span {
|
||||
PlaceSpan::Within(span) => span.within(&own),
|
||||
PlaceSpan::Shifted(mut span) => {
|
||||
span.shift(own.start);
|
||||
span
|
||||
}
|
||||
PlaceSpan::Sized(len) => {
|
||||
let start = own.start + (own.len() - len).scale(align.rel());
|
||||
UiSpan::new(start, start + len)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A child's region along one axis, and what becomes of its placement in
|
||||
/// that region once it has answered.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Place {
|
||||
/// The placement is the child's answer, aligned inside the region by the
|
||||
/// child's alignment.
|
||||
Within(Part),
|
||||
/// The region is the placement; the answer is not placed inside it again.
|
||||
Fill(Part),
|
||||
}
|
||||
|
||||
impl Place {
|
||||
pub(crate) fn part(self) -> Part {
|
||||
match self {
|
||||
Self::Within(part) | Self::Fill(part) => part,
|
||||
/// The child's rel base, where this says one outright. `None` forwards
|
||||
/// the caller's own, and [`RelBase::WithRegion`] is resolved by whoever
|
||||
/// can read that rel base, so it does not reach here.
|
||||
pub(crate) const fn stated_rel_base(self) -> Option<Len> {
|
||||
match self.rel_base {
|
||||
RelBase::Len(len) => Some(len),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the region is the placement outright, rather than a box the
|
||||
/// answer is placed inside.
|
||||
pub(crate) fn fills(self) -> bool {
|
||||
matches!(self, Self::Fill(_))
|
||||
/// The length this narrows the caller's rel base by, where it does.
|
||||
/// `None` leaves that rel base alone, and reading it is then a
|
||||
/// dependency the caller does not take.
|
||||
pub(crate) const fn narrows_rel_base(self) -> Option<UiSpan> {
|
||||
match (self.rel_base, self.span) {
|
||||
(RelBase::WithRegion, PlaceSpan::Within(span)) => Some(span),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The span it composes into the caller's box, where that is what it
|
||||
/// does: the one case whose validity maps back through the part.
|
||||
pub(crate) const fn within_span(self) -> Option<UiSpan> {
|
||||
match self.span {
|
||||
PlaceSpan::Within(span) => Some(span),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the caller decided this length rather than a place along its
|
||||
/// own box, which is what stops its length reaching the child at all.
|
||||
pub(crate) const fn is_sized(self) -> bool {
|
||||
matches!(self.span, PlaceSpan::Sized(_))
|
||||
}
|
||||
|
||||
/// The same, with its rel base stated outright.
|
||||
pub(crate) const fn with_rel_base(mut self, len: Option<Len>) -> Self {
|
||||
self.rel_base = match len {
|
||||
Some(len) => RelBase::Len(len),
|
||||
None => RelBase::Inherit,
|
||||
};
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a child is asked, on both axes. A [`UiRegion`] converts into the
|
||||
/// common case: that box of the caller's own, the answer placed inside it.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct PlaceDesc {
|
||||
pub x: PlaceDescAxis,
|
||||
pub y: PlaceDescAxis,
|
||||
}
|
||||
|
||||
impl PlaceDesc {
|
||||
/// The whole of the caller's box, on both axes.
|
||||
pub const WHOLE: Self = Self::splat(PlaceDescAxis::WHOLE);
|
||||
|
||||
pub const fn new(x: PlaceDescAxis, y: PlaceDescAxis) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
/// The same on both axes.
|
||||
pub const fn splat(place: PlaceDescAxis) -> Self {
|
||||
Self { x: place, y: place }
|
||||
}
|
||||
|
||||
/// `aligned` on `axis` and `ortho` on the other, which is how a
|
||||
/// container that divides one axis says what it is doing.
|
||||
pub fn from_axis(axis: Axis, aligned: PlaceDescAxis, ortho: PlaceDescAxis) -> Self {
|
||||
match axis {
|
||||
Axis::X => Self::new(aligned, ortho),
|
||||
Axis::Y => Self::new(ortho, aligned),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis(&self, axis: Axis) -> &PlaceDescAxis {
|
||||
match axis {
|
||||
Axis::X => &self.x,
|
||||
Axis::Y => &self.y,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn axis_mut(&mut self, axis: Axis) -> &mut PlaceDescAxis {
|
||||
match axis {
|
||||
Axis::X => &mut self.x,
|
||||
Axis::Y => &mut self.y,
|
||||
}
|
||||
}
|
||||
|
||||
/// Both regions are the child's placement. See [`PlaceDescAxis::fills`].
|
||||
pub const fn fills(self) -> Self {
|
||||
Self::new(self.x.fills(), self.y.fills())
|
||||
}
|
||||
|
||||
/// The child's rel base on one axis. See [`PlaceDescAxis::rel_base`].
|
||||
pub const fn rel_base(mut self, axis: Axis, len: Len) -> Self {
|
||||
*self.axis_mut(axis) = self.axis(axis).rel_base(len);
|
||||
self
|
||||
}
|
||||
|
||||
/// The box each axis names, in the coordinates `own` is in.
|
||||
pub(crate) fn of(self, own: UiRegion, align: RegionAlign) -> UiRegion {
|
||||
UiRegion::new(self.x.of(own.x, align.x), self.y.of(own.y, align.y))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UiRegion> for PlaceDesc {
|
||||
fn from(region: UiRegion) -> Self {
|
||||
Self::new(
|
||||
PlaceDescAxis::within(region.x),
|
||||
PlaceDescAxis::within(region.y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PlaceDescAxis> for PlaceDesc {
|
||||
fn from(place: PlaceDescAxis) -> Self {
|
||||
Self::splat(place)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-38
@@ -3,7 +3,7 @@ use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
||||
use crate::ui::painter::{declared_lens, placement, rel_base_and_region};
|
||||
use crate::{
|
||||
ActiveData, Axis, DrawLayers, IdLike, LayoutHolds, LayoutLen, Len, MaskIdx, MoveIdx, Moves,
|
||||
Painter, Part, PixelRegion, Place, PxVec2, Rel, Size, StrongWidget, UiRegion, UiRsc, UiSpan,
|
||||
Painter, PixelRegion, PlaceDesc, PxVec2, Rel, Size, StrongWidget, UiRegion, UiRsc, UiSpan,
|
||||
UiVec2, Weight, WidgetId, Widgets,
|
||||
util::{HashMap, Vec2},
|
||||
};
|
||||
@@ -27,27 +27,16 @@ pub(super) struct DrawInfo {
|
||||
/// coordinates.
|
||||
pub region: UiRegion,
|
||||
/// Where the widget is put, and where it was asked, as parts of the
|
||||
/// parent's box. See [`Place`]. The two are one ask's place until the
|
||||
/// parent's box. See [`PlaceDesc`]. The two are one ask's place until the
|
||||
/// parent puts the answer somewhere else.
|
||||
pub placed: [Place; 2],
|
||||
pub asked: [Place; 2],
|
||||
/// A rel base the parent decided for it on each axis, as a length of the
|
||||
/// window, which the widget's own declaration is a fraction of.
|
||||
pub narrow_rel_base: [Option<Len>; 2],
|
||||
pub placed: PlaceDesc,
|
||||
pub asked: PlaceDesc,
|
||||
/// Whether the parent already asked about this widget in this draw.
|
||||
pub re_asked: bool,
|
||||
/// The rel base in pixels, resolved once against the window.
|
||||
pub px: PxVec2,
|
||||
}
|
||||
|
||||
impl DrawInfo {
|
||||
/// The axes where the part is the drawing's box outright, which are the
|
||||
/// axes the answer is not placed inside it again.
|
||||
fn fill(&self) -> [bool; 2] {
|
||||
self.placed.map(Place::fills)
|
||||
}
|
||||
}
|
||||
|
||||
/// What a widget's children are placed in: its own box, the coordinates its
|
||||
/// drawing is in, and what else one ask of a child is decided from.
|
||||
pub(super) struct Placing {
|
||||
@@ -133,7 +122,7 @@ impl UiRenderState {
|
||||
}
|
||||
}
|
||||
|
||||
/// The root is asked about in the output. Its own rules narrow_rel_base both its
|
||||
/// The root is asked about in the output. Its own rules narrow both its
|
||||
/// rel base and box; nothing above it chose a different one.
|
||||
fn root_info(&self, rel_base: UiVec2, region: UiRegion) -> DrawInfo {
|
||||
let px = rel_base.to_px(self.output_size);
|
||||
@@ -146,9 +135,8 @@ impl UiRenderState {
|
||||
mask: MaskIdx::NONE,
|
||||
rel_base,
|
||||
region,
|
||||
placed: [Place::Within(Part::WHOLE); 2],
|
||||
asked: [Place::Within(Part::WHOLE); 2],
|
||||
narrow_rel_base: [None; 2],
|
||||
placed: PlaceDesc::WHOLE,
|
||||
asked: PlaceDesc::WHOLE,
|
||||
re_asked: false,
|
||||
px,
|
||||
}
|
||||
@@ -209,8 +197,7 @@ impl UiRenderState {
|
||||
rel_base_and_region(
|
||||
UiRegion::FULL,
|
||||
UiVec2::FULL_SIZE,
|
||||
[Place::Within(Part::WHOLE); 2],
|
||||
[None; 2],
|
||||
PlaceDesc::WHOLE,
|
||||
declared_lens(widgets, id),
|
||||
widgets.alignment(id),
|
||||
)
|
||||
@@ -248,7 +235,7 @@ impl UiRenderState {
|
||||
.then(|| self.retained_answer(id, region, info))
|
||||
.flatten()
|
||||
.and_then(|answer| {
|
||||
let placed = placement(region, answer.0, declared, info.fill(), align);
|
||||
let placed = placement(region, answer.0, declared, info.placed, align);
|
||||
self.try_reuse(id, region, placed, info, rsc)
|
||||
.map(|()| answer)
|
||||
});
|
||||
@@ -260,7 +247,7 @@ impl UiRenderState {
|
||||
// Where the drawing goes: the part its parent gave it, with the
|
||||
// answer placed inside that part on any axis the parent left
|
||||
// open.
|
||||
let placed = placement(region, answer.0, declared, info.fill(), align);
|
||||
let placed = placement(region, answer.0, declared, info.placed, align);
|
||||
if placed != region {
|
||||
self.relocate(id, placed, info, rsc);
|
||||
}
|
||||
@@ -273,7 +260,6 @@ impl UiRenderState {
|
||||
// and what of its own box it asked in. A local redraw asks the same
|
||||
// question again from these.
|
||||
active.rel_base = info.rel_base;
|
||||
active.narrow_rel_base = info.narrow_rel_base;
|
||||
active.re_asked = info.re_asked;
|
||||
active.answer = Some(answer);
|
||||
active.asked = info.asked;
|
||||
@@ -468,9 +454,8 @@ impl UiRenderState {
|
||||
mask,
|
||||
rel_base: UiVec2::FULL_SIZE,
|
||||
region: UiRegion::FULL,
|
||||
placed: [Place::Within(Part::WHOLE); 2],
|
||||
asked: [Place::Within(Part::WHOLE); 2],
|
||||
narrow_rel_base: [None; 2],
|
||||
placed: PlaceDesc::WHOLE,
|
||||
asked: PlaceDesc::WHOLE,
|
||||
re_asked: false,
|
||||
px,
|
||||
},
|
||||
@@ -484,7 +469,6 @@ impl UiRenderState {
|
||||
id,
|
||||
placement: region,
|
||||
rel_base: info.rel_base,
|
||||
narrow_rel_base: info.narrow_rel_base,
|
||||
placed: info.placed,
|
||||
asked: info.asked,
|
||||
region,
|
||||
@@ -718,7 +702,7 @@ impl UiRenderState {
|
||||
&mut self,
|
||||
child: WidgetId,
|
||||
at: &Placing,
|
||||
place: [Place; 2],
|
||||
place: PlaceDesc,
|
||||
rsc: &mut dyn UiRsc,
|
||||
) {
|
||||
let active = &self.active[&child];
|
||||
@@ -727,7 +711,7 @@ impl UiRenderState {
|
||||
region,
|
||||
active.measured().unwrap_or(active.size),
|
||||
active.declared,
|
||||
place.map(Place::fills),
|
||||
place,
|
||||
active.own_align,
|
||||
);
|
||||
let info = DrawInfo {
|
||||
@@ -741,7 +725,6 @@ impl UiRenderState {
|
||||
region,
|
||||
placed: place,
|
||||
asked: active.asked,
|
||||
narrow_rel_base: active.narrow_rel_base,
|
||||
re_asked: active.re_asked,
|
||||
px: rel_base.to_px(at.window),
|
||||
};
|
||||
@@ -752,12 +735,11 @@ impl UiRenderState {
|
||||
/// the box its parent is being taken as. What narrowed its rel base and what
|
||||
/// it declared are its own record's, so both are resolved against that
|
||||
/// parent's rel base again exactly as the first ask resolved them.
|
||||
fn ask_again(active: &ActiveData, at: &Placing, place: [Place; 2]) -> (UiVec2, UiRegion) {
|
||||
fn ask_again(active: &ActiveData, at: &Placing, place: PlaceDesc) -> (UiVec2, UiRegion) {
|
||||
rel_base_and_region(
|
||||
at.region,
|
||||
at.rel_base,
|
||||
place,
|
||||
active.narrow_rel_base,
|
||||
active.declared,
|
||||
active.own_align,
|
||||
)
|
||||
@@ -886,9 +868,8 @@ impl UiRenderState {
|
||||
id,
|
||||
placement: UiRegion::FULL,
|
||||
rel_base: UiVec2::FULL_SIZE,
|
||||
narrow_rel_base: [None; 2],
|
||||
placed: [Place::Within(Part::WHOLE); 2],
|
||||
asked: [Place::Within(Part::WHOLE); 2],
|
||||
placed: PlaceDesc::WHOLE,
|
||||
asked: PlaceDesc::WHOLE,
|
||||
region: UiRegion::FULL,
|
||||
answer: None,
|
||||
re_asked: false,
|
||||
@@ -1146,7 +1127,6 @@ impl UiRenderState {
|
||||
region,
|
||||
placed: active.asked,
|
||||
asked: active.asked,
|
||||
narrow_rel_base: active.narrow_rel_base,
|
||||
re_asked: false,
|
||||
px: rel_base.to_px(self.output_size),
|
||||
};
|
||||
@@ -1171,7 +1151,7 @@ impl UiRenderState {
|
||||
}
|
||||
if active.answer != was_answer || active.holds != was_holds {
|
||||
// The parent retains both the answer and the drawing's validity;
|
||||
// even an unchanged size can narrow_rel_base the range safe for a resize.
|
||||
// even an unchanged size can narrow the range safe for a resize.
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
{
|
||||
diag::bump(Counter::SizeChanges);
|
||||
|
||||
+6
-6
@@ -118,9 +118,9 @@ pub struct Branch {
|
||||
impl Widget for Branch {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
let cut = Len::from_parts(Rel::ZERO, Px::from_int(40));
|
||||
let top = Place::Within(Part::From(UiSpan::new(Len::ZERO, cut)));
|
||||
let top = PlaceDescAxis::shifted(UiSpan::new(Len::ZERO, cut));
|
||||
let measured = painter
|
||||
.widget_at(&self.probe, [Place::Within(Part::WHOLE), top], None)
|
||||
.widget_at(&self.probe, PlaceDesc::new(PlaceDescAxis::WHOLE, top))
|
||||
.len(Axis::X);
|
||||
let len = measured.apply_leftover();
|
||||
let px = painter.to_px(len, Axis::X);
|
||||
@@ -134,11 +134,11 @@ impl Widget for Branch {
|
||||
};
|
||||
painter.window_holds(Axis::X, holds.through(len));
|
||||
|
||||
let below = Place::Within(Part::From(UiSpan::new(cut, painter.region_len(Axis::Y))));
|
||||
let place = [Place::Within(Part::WHOLE), below];
|
||||
let below = PlaceDescAxis::shifted(UiSpan::new(cut, painter.region_len(Axis::Y)));
|
||||
let place = PlaceDesc::new(PlaceDescAxis::WHOLE, below);
|
||||
match px > threshold {
|
||||
true => painter.widget_at(&self.wide, place, None),
|
||||
false => painter.widget_at(&self.narrow, place, None),
|
||||
true => painter.widget_at(&self.wide, place),
|
||||
false => painter.widget_at(&self.narrow, place),
|
||||
};
|
||||
Size::LEFTOVER
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ pub struct Offset {
|
||||
impl Widget for Offset {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
painter
|
||||
.widget_within(&self.inner, UiRegion::FULL.offset(self.amt))
|
||||
.widget_at(&self.inner, UiRegion::FULL.offset(self.amt))
|
||||
.size()
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,7 @@ impl Widget for Pad {
|
||||
// padding, and it comes off the box, so what is drawn sits inside.
|
||||
// The two stay distinct -- the box can be narrower still, where a row
|
||||
// asked this widget in the room left, and a text wraps at that.
|
||||
let inner = painter
|
||||
.widget_within(&self.inner, self.padding.region())
|
||||
.size();
|
||||
let inner = painter.widget_at(&self.inner, self.padding.region()).size();
|
||||
Size {
|
||||
x: LayoutLen {
|
||||
px: inner.x.px + self.padding.left + self.padding.right,
|
||||
|
||||
@@ -14,7 +14,7 @@ impl Widget for Scroll {
|
||||
let container_len = painter.px_len(self.axis);
|
||||
// Asked in the whole viewport, then put at the scrolled offset.
|
||||
let answer_len = painter
|
||||
.widget_at(&self.inner, [Place::Fill(Part::WHOLE); 2], None)
|
||||
.widget_at(&self.inner, PlaceDesc::WHOLE.fills())
|
||||
.len(self.axis);
|
||||
let fixed = painter.to_px(Len::from_parts(answer_len.rel, answer_len.px), self.axis);
|
||||
self.container_len = container_len;
|
||||
@@ -54,9 +54,9 @@ impl Widget for Scroll {
|
||||
let content = match moved || self.content_len != self.container_len {
|
||||
true => {
|
||||
let start = Len::from_parts(Rel::ZERO, anchor - self.amt);
|
||||
Part::From(UiSpan::new(start, start.offset(self.content_len)))
|
||||
PlaceDescAxis::shifted(UiSpan::new(start, start.offset(self.content_len)))
|
||||
}
|
||||
false => Part::WHOLE,
|
||||
false => PlaceDescAxis::WHOLE,
|
||||
};
|
||||
// The viewport is the inner's rel base, so a fraction it declares or
|
||||
// reports is a fraction of what is on screen rather than of the
|
||||
@@ -64,9 +64,7 @@ impl Widget for Scroll {
|
||||
// box, scrolled: its drawing moved there, not made again there.
|
||||
painter.place_at(
|
||||
&self.inner,
|
||||
self.axis
|
||||
.pair(Place::Fill(content), Place::Fill(Part::WHOLE)),
|
||||
None,
|
||||
PlaceDesc::from_axis(self.axis, content.fills(), PlaceDescAxis::WHOLE.fills()),
|
||||
);
|
||||
// What it occupies is its box, on both axes: it clips its content to
|
||||
// that box, so it can neither take less of one nor honestly ask for
|
||||
|
||||
@@ -21,7 +21,7 @@ impl Widget for Span {
|
||||
// Across itself the child sits where its own alignment says, in the
|
||||
// whole of the row: a span is what contains its children there, and
|
||||
// nothing divides that axis.
|
||||
let across = Place::Within(Part::WHOLE);
|
||||
let across = PlaceDescAxis::WHOLE;
|
||||
// A length for every child before their final slots are chosen: from
|
||||
// a hint where one says, and from drawing otherwise. The rel base passes
|
||||
// through unchanged, so `rel(0.5)` is half the area this span was
|
||||
@@ -34,9 +34,9 @@ impl Widget for Span {
|
||||
let len = match painter.size_hint(child, axis) {
|
||||
Some(len) => len,
|
||||
None => {
|
||||
let room = Place::Within(Part::From(along(cursor, far)));
|
||||
let room = PlaceDescAxis::shifted(along(cursor, far));
|
||||
painter
|
||||
.widget_at(child, axis.pair(room, across), None)
|
||||
.widget_at(child, PlaceDesc::from_axis(axis, room, across))
|
||||
.len(axis)
|
||||
}
|
||||
};
|
||||
@@ -120,10 +120,12 @@ impl Widget for Span {
|
||||
// fixed child's slot is its own answer, so a drawing made in the
|
||||
// room is put there as it is, and one not made yet is made here.
|
||||
let slot = along(from, start);
|
||||
let place = axis.pair(Place::Fill(Part::From(slot)), across);
|
||||
let narrow =
|
||||
(len.leftover > Weight::ZERO && shares).then(|| axis.pair(Some(slot.len()), None));
|
||||
let used = painter.place_at(child, place, narrow).len(!axis);
|
||||
let slot_place = PlaceDescAxis::shifted(slot).fills();
|
||||
let mut place = PlaceDesc::from_axis(axis, slot_place, across);
|
||||
if len.leftover > Weight::ZERO && shares {
|
||||
place = place.rel_base(axis, slot.len());
|
||||
}
|
||||
let used = painter.place_at(child, place).len(!axis);
|
||||
if shrinks {
|
||||
// Choosing between a fixed and a relative length from the
|
||||
// span's own eventual width admits multiple fixed points.
|
||||
|
||||
@@ -22,9 +22,7 @@ impl Widget for Stack {
|
||||
// drawing belongs to the layer it was made on.
|
||||
Some((i, child)) => {
|
||||
painter.child_layer_at(i);
|
||||
painter
|
||||
.widget_at(child, [Place::Fill(Part::WHOLE); 2], None)
|
||||
.size()
|
||||
painter.widget_at(child, PlaceDesc::WHOLE.fills()).size()
|
||||
}
|
||||
None => Size::LEFTOVER,
|
||||
};
|
||||
@@ -33,19 +31,20 @@ impl Widget for Stack {
|
||||
// fraction under them is a fraction of it. A share leaves the axis
|
||||
// to whoever gave the stack its box. Where a child sits in a box
|
||||
// bigger than itself is its own business.
|
||||
let place = [Axis::X, Axis::Y].map(|axis| {
|
||||
let on = |axis| {
|
||||
let len = size.axis(axis);
|
||||
match len.leftover == Weight::ZERO {
|
||||
true => Place::Fill(Part::Sized(Len::from_parts(len.rel, len.px))),
|
||||
false => Place::Within(Part::WHOLE),
|
||||
true => PlaceDescAxis::sized(Len::from_parts(len.rel, len.px)).fills(),
|
||||
false => PlaceDescAxis::WHOLE,
|
||||
}
|
||||
});
|
||||
};
|
||||
let place = PlaceDesc::new(on(Axis::X), on(Axis::Y));
|
||||
for (i, child) in self.children.iter().enumerate() {
|
||||
if sizing == Some(i) {
|
||||
continue;
|
||||
}
|
||||
painter.child_layer_at(i);
|
||||
painter.widget_at(child, place, None);
|
||||
painter.widget_at(child, place);
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
@@ -22,17 +22,17 @@ struct BranchesOnMeasurement {
|
||||
impl Widget for BranchesOnMeasurement {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
let cut = Len::from_parts(Rel::ZERO, Px::from_int(40));
|
||||
let top = Place::Within(Part::From(UiSpan::new(Len::ZERO, cut)));
|
||||
let top = PlaceDescAxis::shifted(UiSpan::new(Len::ZERO, cut));
|
||||
let measured = painter
|
||||
.widget_at(&self.probe, [Place::Within(Part::WHOLE), top], None)
|
||||
.widget_at(&self.probe, PlaceDesc::new(PlaceDescAxis::WHOLE, top))
|
||||
.len(Axis::X);
|
||||
let px = painter.to_px(measured.apply_leftover(), Axis::X);
|
||||
|
||||
let below = Place::Within(Part::From(UiSpan::new(cut, painter.region_len(Axis::Y))));
|
||||
let place = [Place::Within(Part::WHOLE), below];
|
||||
let below = PlaceDescAxis::shifted(UiSpan::new(cut, painter.region_len(Axis::Y)));
|
||||
let place = PlaceDesc::new(PlaceDescAxis::WHOLE, below);
|
||||
match px > Px::from_f32(self.threshold) {
|
||||
true => painter.widget_at(&self.wide, place, None),
|
||||
false => painter.widget_at(&self.narrow, place, None),
|
||||
true => painter.widget_at(&self.wide, place),
|
||||
false => painter.widget_at(&self.narrow, place),
|
||||
};
|
||||
Size::LEFTOVER
|
||||
}
|
||||
|
||||
+28
-33
@@ -216,8 +216,7 @@ impl Widget for FromHint {
|
||||
let top = UiSpan::new(Len::ZERO, Len::from_parts(Rel::ZERO, len.px));
|
||||
painter.widget_at(
|
||||
&self.inner,
|
||||
[Place::Within(Part::WHOLE), Place::Within(Part::From(top))],
|
||||
None,
|
||||
PlaceDesc::new(PlaceDescAxis::WHOLE, PlaceDescAxis::shifted(top)),
|
||||
);
|
||||
Size::LEFTOVER
|
||||
}
|
||||
@@ -877,11 +876,10 @@ fn resizing_a_fixed_frame_recomposes_its_contents_without_drawing_them() {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
painter.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Within(Part::From(self.region.x)),
|
||||
Place::Within(Part::From(self.region.y)),
|
||||
],
|
||||
None,
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(self.region.x),
|
||||
PlaceDescAxis::shifted(self.region.y),
|
||||
),
|
||||
);
|
||||
Size::LEFTOVER
|
||||
}
|
||||
@@ -966,11 +964,11 @@ fn glyph_origins_compose_identically_when_drawn_and_when_retained() {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
painter.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Fill(Part::From(self.region.x)),
|
||||
Place::Fill(Part::From(self.region.y)),
|
||||
],
|
||||
[Some(self.frame.x.len()), None],
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(self.region.x).fills(),
|
||||
PlaceDescAxis::shifted(self.region.y).fills(),
|
||||
)
|
||||
.rel_base(Axis::X, self.frame.x.len()),
|
||||
);
|
||||
Size::LEFTOVER
|
||||
}
|
||||
@@ -1136,11 +1134,10 @@ fn padding_and_stack_boxes_follow_the_region_without_drawing_again() {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
painter.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Fill(Part::From(self.region.x)),
|
||||
Place::Fill(Part::From(self.region.y)),
|
||||
],
|
||||
None,
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(self.region.x).fills(),
|
||||
PlaceDescAxis::shifted(self.region.y).fills(),
|
||||
),
|
||||
);
|
||||
Size::LEFTOVER
|
||||
}
|
||||
@@ -1224,14 +1221,14 @@ fn moving_a_childs_region_preserves_the_slot_chosen_from_its_measurement() {
|
||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||
painter.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Fill(Part::From(UiSpan::new(
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(UiSpan::new(
|
||||
Len::px(self.start),
|
||||
Len::px(self.start + 200.0),
|
||||
))),
|
||||
Place::Fill(Part::From(UiSpan::FULL)),
|
||||
],
|
||||
None,
|
||||
))
|
||||
.fills(),
|
||||
PlaceDescAxis::shifted(UiSpan::FULL).fills(),
|
||||
),
|
||||
);
|
||||
Size::LEFTOVER
|
||||
}
|
||||
@@ -1266,11 +1263,10 @@ fn changing_regions_keep_fractional_reports_and_numeric_dependencies_valid() {
|
||||
painter
|
||||
.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Within(Part::From(self.region.x)),
|
||||
Place::Within(Part::From(self.region.y)),
|
||||
],
|
||||
None,
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(self.region.x),
|
||||
PlaceDescAxis::shifted(self.region.y),
|
||||
),
|
||||
)
|
||||
.size()
|
||||
}
|
||||
@@ -1286,11 +1282,10 @@ fn changing_regions_keep_fractional_reports_and_numeric_dependencies_valid() {
|
||||
painter
|
||||
.widget_at(
|
||||
&self.child,
|
||||
[
|
||||
Place::Fill(Part::From(self.region.x)),
|
||||
Place::Fill(Part::From(self.region.y)),
|
||||
],
|
||||
None,
|
||||
PlaceDesc::new(
|
||||
PlaceDescAxis::shifted(self.region.x).fills(),
|
||||
PlaceDescAxis::shifted(self.region.y).fills(),
|
||||
),
|
||||
)
|
||||
.size(),
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user