Say region and placement, not extent
The split box was named `region` and `placement` on 2026-09-17; `frame` came back as a length and survived, `extent` did not. It stayed as the name for both halves, distinguished only by prose: `draw_at` bound the caller's `part` to a parameter called `extent`, and `ActiveData` held two `UiRegion`s that `draw_at` wrote `part: extent` from. The box a parent asks a widget in is now the region, and where its drawing ends up is its placement. `Painter`'s four holds accumulators become the one `LayoutHolds` they were assembled into, which also drops the name mapping between them. The cold dump of 400 depth-5 trees is byte-identical across the change.
This commit is contained in:
1 parent
84dad211f5
commit
5642f2010a
13 files changed
+212
-227
No files matched your search
@@ -54,11 +54,11 @@ pub(crate) enum Counter {
|
|||||||
GlyphPlacements,
|
GlyphPlacements,
|
||||||
OutsidePinnedLen,
|
OutsidePinnedLen,
|
||||||
OutsideFrame,
|
OutsideFrame,
|
||||||
OutsideExtent,
|
OutsideRegion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Counter {
|
impl Counter {
|
||||||
const COUNT: usize = Self::OutsideExtent as usize + 1;
|
const COUNT: usize = Self::OutsideRegion as usize + 1;
|
||||||
|
|
||||||
const NAMES: [&'static str; Self::COUNT] = [
|
const NAMES: [&'static str; Self::COUNT] = [
|
||||||
"updates",
|
"updates",
|
||||||
@@ -90,7 +90,7 @@ impl Counter {
|
|||||||
"glyph placements",
|
"glyph placements",
|
||||||
"reuse outside: the length it was pinned to",
|
"reuse outside: the length it was pinned to",
|
||||||
"reuse outside: a frame length",
|
"reuse outside: a frame length",
|
||||||
"reuse outside: an extent length",
|
"reuse outside: a region length",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::{
|
|||||||
pub struct ActiveData {
|
pub struct ActiveData {
|
||||||
pub id: WidgetId,
|
pub id: WidgetId,
|
||||||
/// Where its drawing goes, in its region node's coordinates.
|
/// Where its drawing goes, in its region node's coordinates.
|
||||||
pub extent: UiRegion,
|
pub placement: UiRegion,
|
||||||
/// What a fraction declared or reported under this widget is a fraction
|
/// What a fraction declared or reported under this widget is a fraction
|
||||||
/// of, as a length of the window.
|
/// of, as a length of the window.
|
||||||
pub frame: UiVec2,
|
pub frame: UiVec2,
|
||||||
@@ -29,7 +29,7 @@ pub struct ActiveData {
|
|||||||
/// The box it was asked in, in the parent's region-node coordinates: the
|
/// 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
|
/// 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.
|
/// drawing is placed elsewhere by re-expression, never by asking again.
|
||||||
pub part: UiRegion,
|
pub region: UiRegion,
|
||||||
/// The measured answer and its dependencies. A hint-only dependency or
|
/// The measured answer and its dependencies. A hint-only dependency or
|
||||||
/// a widget first encountered during placement has no measurement yet.
|
/// a widget first encountered during placement has no measurement yet.
|
||||||
pub answer: Option<(Size, LayoutHolds)>,
|
pub answer: Option<(Size, LayoutHolds)>,
|
||||||
@@ -40,8 +40,8 @@ pub struct ActiveData {
|
|||||||
pub re_asked: bool,
|
pub re_asked: bool,
|
||||||
/// What the widget reported, in window-unit lengths.
|
/// What the widget reported, in window-unit lengths.
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
/// The window and extent reads that this drawing holds for, and the
|
/// The window and region reads that this drawing holds for, and the
|
||||||
/// frame and box it pinned.
|
/// frame and region it pinned.
|
||||||
pub holds: LayoutHolds,
|
pub holds: LayoutHolds,
|
||||||
pub drawn: bool,
|
pub drawn: bool,
|
||||||
pub parent: Option<WidgetId>,
|
pub parent: Option<WidgetId>,
|
||||||
@@ -51,7 +51,7 @@ pub struct ActiveData {
|
|||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
pub textures: Vec<TextureHandle>,
|
pub textures: Vec<TextureHandle>,
|
||||||
/// Its primitives, each keeping the box it was written in -- in this
|
/// Its primitives, each keeping the box it was written in -- in this
|
||||||
/// widget's extent coordinates, which is what a move recomposes from.
|
/// widget's placement coordinates, which is what a move recomposes from.
|
||||||
pub primitives: Vec<RetainedPrimitive>,
|
pub primitives: Vec<RetainedPrimitive>,
|
||||||
/// An owned mask holds one reference independently of its primitives.
|
/// An owned mask holds one reference independently of its primitives.
|
||||||
pub mask_region: Option<UiRegion>,
|
pub mask_region: Option<UiRegion>,
|
||||||
@@ -68,8 +68,8 @@ pub struct ActiveData {
|
|||||||
/// Its alignment when it was last drawn, which a change to the property
|
/// Its alignment when it was last drawn, which a change to the property
|
||||||
/// is found against.
|
/// is found against.
|
||||||
pub own_align: RegionAlign,
|
pub own_align: RegionAlign,
|
||||||
/// The movable region whose coordinates `extent` uses when this widget
|
/// The movable region whose coordinates its placement is in when this
|
||||||
/// does not own a region node.
|
/// widget does not own a region node.
|
||||||
pub parent_move: MoveIdx,
|
pub parent_move: MoveIdx,
|
||||||
/// The mask its drawing is clipped to: one it set itself, or the one it
|
/// The mask its drawing is clipped to: one it set itself, or the one it
|
||||||
/// inherited from whoever drew it.
|
/// inherited from whoever drew it.
|
||||||
|
|||||||
+16
-16
@@ -22,34 +22,34 @@ const AXES: [Axis; 2] = [Axis::X, Axis::Y];
|
|||||||
pub struct LayoutHolds {
|
pub struct LayoutHolds {
|
||||||
pub window: [Holds; 2],
|
pub window: [Holds; 2],
|
||||||
pub frame_len: [Option<Len>; 2],
|
pub frame_len: [Option<Len>; 2],
|
||||||
pub extent: [Holds; 2],
|
pub region: [Holds; 2],
|
||||||
pub extent_len: [Option<Len>; 2],
|
pub region_len: [Option<Len>; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutHolds {
|
impl LayoutHolds {
|
||||||
pub const ANY: Self = Self {
|
pub const ANY: Self = Self {
|
||||||
window: [Holds::ANY; 2],
|
window: [Holds::ANY; 2],
|
||||||
frame_len: [None; 2],
|
frame_len: [None; 2],
|
||||||
extent: [Holds::ANY; 2],
|
region: [Holds::ANY; 2],
|
||||||
extent_len: [None; 2],
|
region_len: [None; 2],
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn and(self, other: Self) -> Self {
|
pub fn and(self, other: Self) -> Self {
|
||||||
let mut result = Self::ANY;
|
let mut result = Self::ANY;
|
||||||
for n in 0..2 {
|
for n in 0..2 {
|
||||||
result.window[n] = self.window[n].and(other.window[n]);
|
result.window[n] = self.window[n].and(other.window[n]);
|
||||||
result.extent[n] = self.extent[n].and(other.extent[n]);
|
result.region[n] = self.region[n].and(other.region[n]);
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.extent_len[n].is_none()
|
self.region_len[n].is_none()
|
||||||
|| other.extent_len[n].is_none()
|
|| other.region_len[n].is_none()
|
||||||
|| self.extent_len[n] == other.extent_len[n]
|
|| self.region_len[n] == other.region_len[n]
|
||||||
);
|
);
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.frame_len[n].is_none()
|
self.frame_len[n].is_none()
|
||||||
|| other.frame_len[n].is_none()
|
|| other.frame_len[n].is_none()
|
||||||
|| self.frame_len[n] == other.frame_len[n]
|
|| self.frame_len[n] == other.frame_len[n]
|
||||||
);
|
);
|
||||||
result.extent_len[n] = self.extent_len[n].or(other.extent_len[n]);
|
result.region_len[n] = self.region_len[n].or(other.region_len[n]);
|
||||||
result.frame_len[n] = self.frame_len[n].or(other.frame_len[n]);
|
result.frame_len[n] = self.frame_len[n].or(other.frame_len[n]);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@@ -59,21 +59,21 @@ impl LayoutHolds {
|
|||||||
(0..2).all(|n| {
|
(0..2).all(|n| {
|
||||||
self.window[n].lo <= other.window[n].lo
|
self.window[n].lo <= other.window[n].lo
|
||||||
&& self.window[n].hi >= other.window[n].hi
|
&& self.window[n].hi >= other.window[n].hi
|
||||||
&& self.extent[n].lo <= other.extent[n].lo
|
&& self.region[n].lo <= other.region[n].lo
|
||||||
&& self.extent[n].hi >= other.extent[n].hi
|
&& self.region[n].hi >= other.region[n].hi
|
||||||
&& self.extent_len[n].is_none_or(|len| other.extent_len[n] == Some(len))
|
&& self.region_len[n].is_none_or(|len| other.region_len[n] == Some(len))
|
||||||
&& self.frame_len[n].is_none_or(|len| other.frame_len[n] == Some(len))
|
&& self.frame_len[n].is_none_or(|len| other.frame_len[n] == Some(len))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(self, window: PxVec2, frame: UiVec2, extent: UiRegion) -> bool {
|
pub fn contains(self, window: PxVec2, frame: UiVec2, region: UiRegion) -> bool {
|
||||||
AXES.into_iter().all(|axis| {
|
AXES.into_iter().all(|axis| {
|
||||||
let n = axis as usize;
|
let n = axis as usize;
|
||||||
let len = extent.axis(axis).len();
|
let len = region.axis(axis).len();
|
||||||
self.window[n].contains(window.axis(axis))
|
self.window[n].contains(window.axis(axis))
|
||||||
&& self.frame_len[n].is_none_or(|pinned| pinned == frame.axis(axis))
|
&& self.frame_len[n].is_none_or(|pinned| pinned == frame.axis(axis))
|
||||||
&& self.extent[n].contains(len.to_px(window.axis(axis)))
|
&& self.region[n].contains(len.to_px(window.axis(axis)))
|
||||||
&& self.extent_len[n].is_none_or(|pinned| pinned == len)
|
&& self.region_len[n].is_none_or(|pinned| pinned == len)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+59
-64
@@ -22,12 +22,9 @@ pub struct Painter<'a> {
|
|||||||
/// of. A length rather than a box, so padding can take from both the
|
/// of. A length rather than a box, so padding can take from both the
|
||||||
/// frame and the box without either becoming the other.
|
/// frame and the box without either becoming the other.
|
||||||
pub(super) frame: UiVec2,
|
pub(super) frame: UiVec2,
|
||||||
/// Where this widget's drawing goes, in its region node's coordinates.
|
/// The box this widget was asked in, in its region node's coordinates:
|
||||||
pub(super) extent: UiRegion,
|
/// what it draws in, and what its children's places are parts of.
|
||||||
/// The extent's symbolic length where this draw read it, which makes the
|
pub(super) region: UiRegion,
|
||||||
/// drawing one that holds for that length alone -- the way reading a
|
|
||||||
/// length in pixels makes it hold for that number of pixels.
|
|
||||||
pub(super) extent_len: [Option<Len>; 2],
|
|
||||||
/// The window in pixels. Frames and boxes become pixels against this one
|
/// The window in pixels. Frames and boxes become pixels against this one
|
||||||
/// unit, regardless of region-node boundaries.
|
/// unit, regardless of region-node boundaries.
|
||||||
pub(super) window: PxVec2,
|
pub(super) window: PxVec2,
|
||||||
@@ -42,14 +39,12 @@ pub struct Painter<'a> {
|
|||||||
pub(super) children: Vec<WidgetId>,
|
pub(super) children: Vec<WidgetId>,
|
||||||
/// The children whose size this widget read while drawing.
|
/// The children whose size this widget read while drawing.
|
||||||
pub(super) size_deps: Vec<WidgetId>,
|
pub(super) size_deps: Vec<WidgetId>,
|
||||||
/// What this draw itself read of the window in pixels, per axis: every
|
/// What this draw itself reads, as against what its children's drawings
|
||||||
/// window until it reads one, then that one, unless it says otherwise.
|
/// hold for: every window and every length of its own region until it
|
||||||
pub(super) window_own: [Holds; 2],
|
/// reads one, then that one unless it says otherwise, and the frame or
|
||||||
/// Its frame's symbolic length where this draw read it, which makes the
|
/// region length it read symbolically, each of which makes the drawing
|
||||||
/// drawing one that holds for that frame alone.
|
/// hold for that length alone.
|
||||||
pub(super) frame_own_len: [Option<Len>; 2],
|
pub(super) own: LayoutHolds,
|
||||||
/// The window reads' equivalent for its own box.
|
|
||||||
pub(super) extent_own: [Holds; 2],
|
|
||||||
/// What each child's drawing depends on. Asking a child again replaces
|
/// What each child's drawing depends on. Asking a child again replaces
|
||||||
/// its drawing, so it replaces this too rather than narrowing it.
|
/// its drawing, so it replaces this too rather than narrowing it.
|
||||||
pub(super) under: Vec<(WidgetId, LayoutHolds)>,
|
pub(super) under: Vec<(WidgetId, LayoutHolds)>,
|
||||||
@@ -75,10 +70,10 @@ impl<'a> Painter<'a> {
|
|||||||
self.write_resolved(kind, primitive, region, self.resolve(region));
|
self.write_resolved(kind, primitive, region, self.resolve(region));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box in this widget's extent coordinates, composed into its region
|
/// A box in this widget's region, composed into its region node's
|
||||||
/// node's coordinates.
|
/// coordinates.
|
||||||
fn resolve(&self, region: UiRegion) -> UiRegion {
|
fn resolve(&self, region: UiRegion) -> UiRegion {
|
||||||
region.within(&self.extent)
|
region.within(&self.region)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_resolved<P: Primitive>(
|
fn write_resolved<P: Primitive>(
|
||||||
@@ -182,12 +177,12 @@ impl<'a> Painter<'a> {
|
|||||||
let region_node = self.rsc.widgets().is_region_node(id.id());
|
let region_node = self.rsc.widgets().is_region_node(id.id());
|
||||||
let declared = self.declared_lens(id);
|
let declared = self.declared_lens(id);
|
||||||
let align = self.rsc.widgets().alignment(id.id());
|
let align = self.rsc.widgets().alignment(id.id());
|
||||||
let (frame, extent) =
|
let (frame, region) =
|
||||||
frame_and_extent(self.extent, self.frame, place, narrow, declared, align);
|
frame_and_region(self.region, self.frame, place, narrow, declared, align);
|
||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
if region_node {
|
if region_node {
|
||||||
diag::bump(Counter::RegionNodeDraws);
|
diag::bump(Counter::RegionNodeDraws);
|
||||||
diag::region_node(id.id(), self.id, extent);
|
diag::region_node(id.id(), self.id, region);
|
||||||
}
|
}
|
||||||
// A child listed twice would be moved twice.
|
// A child listed twice would be moved twice.
|
||||||
let re_asked = self.children.contains(&id.id());
|
let re_asked = self.children.contains(&id.id());
|
||||||
@@ -205,7 +200,7 @@ impl<'a> Painter<'a> {
|
|||||||
region_node,
|
region_node,
|
||||||
mask: self.mask,
|
mask: self.mask,
|
||||||
frame,
|
frame,
|
||||||
part: extent,
|
region,
|
||||||
placed: place,
|
placed: place,
|
||||||
asked: place,
|
asked: place,
|
||||||
narrow,
|
narrow,
|
||||||
@@ -215,8 +210,8 @@ impl<'a> Painter<'a> {
|
|||||||
None,
|
None,
|
||||||
self.rsc,
|
self.rsc,
|
||||||
);
|
);
|
||||||
let holds = self.in_parent(holds, extent, place, narrow, declared);
|
let holds = self.in_parent(holds, region, place, narrow, declared);
|
||||||
let answer_holds = self.in_parent(answer_holds, extent, place, narrow, declared);
|
let answer_holds = self.in_parent(answer_holds, region, place, narrow, declared);
|
||||||
match self.under.iter_mut().find(|(child, _)| *child == id.id()) {
|
match self.under.iter_mut().find(|(child, _)| *child == id.id()) {
|
||||||
Some((_, kept)) => *kept = holds,
|
Some((_, kept)) => *kept = holds,
|
||||||
None => self.under.push((id.id(), holds)),
|
None => self.under.push((id.id(), holds)),
|
||||||
@@ -256,7 +251,7 @@ impl<'a> Painter<'a> {
|
|||||||
fn placing(&self) -> Placing {
|
fn placing(&self) -> Placing {
|
||||||
Placing {
|
Placing {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
extent: self.extent,
|
region: self.region,
|
||||||
frame: self.frame,
|
frame: self.frame,
|
||||||
window: self.window,
|
window: self.window,
|
||||||
depth: self.depth,
|
depth: self.depth,
|
||||||
@@ -303,7 +298,7 @@ impl<'a> Painter<'a> {
|
|||||||
// the child's own: resolved against a frame of pixels, none is
|
// the child's own: resolved against a frame of pixels, none is
|
||||||
// left to see it by.
|
// left to see it by.
|
||||||
if hint.rel != Rel::ZERO {
|
if hint.rel != Rel::ZERO {
|
||||||
self.frame_own_len[axis as usize] = Some(frame);
|
self.own.frame_len[axis as usize] = Some(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resolved
|
resolved
|
||||||
@@ -327,11 +322,11 @@ impl<'a> Painter<'a> {
|
|||||||
ui.text.render(buffer, attrs, width)
|
ui.text.render(buffer, attrs, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes glyphs in the selected frame or extent coordinates.
|
/// Writes glyphs in the selected frame or region coordinates.
|
||||||
// TODO: merge the text methods into the primitive ones.
|
// TODO: merge the text methods into the primitive ones.
|
||||||
pub fn glyphs(&mut self, text: &RenderedText, origin: UiRegion) {
|
pub fn glyphs(&mut self, text: &RenderedText, origin: UiRegion) {
|
||||||
// Glyph offsets and sizes are pixels, which compose additively.
|
// Glyph offsets and sizes are pixels, which compose additively.
|
||||||
// Only the shared origin needs composing through the extent.
|
// Only the shared origin needs composing through the region.
|
||||||
let resolved = self.resolve(origin);
|
let resolved = self.resolve(origin);
|
||||||
let kind = self.rsc.ui_mut().primitives.kind::<GlyphPrimitive>();
|
let kind = self.rsc.ui_mut().primitives.kind::<GlyphPrimitive>();
|
||||||
for glyph in text.glyphs.iter() {
|
for glyph in text.glyphs.iter() {
|
||||||
@@ -368,9 +363,9 @@ impl<'a> Painter<'a> {
|
|||||||
/// starts, which is what lets a container move without being drawn
|
/// starts, which is what lets a container move without being drawn
|
||||||
/// again. One axis at a time, because a container that divides one axis
|
/// again. One axis at a time, because a container that divides one axis
|
||||||
/// holds for any length of the other.
|
/// holds for any length of the other.
|
||||||
pub fn extent_len(&mut self, axis: Axis) -> Len {
|
pub fn region_len(&mut self, axis: Axis) -> Len {
|
||||||
let len = self.extent.axis(axis).len();
|
let len = self.region.axis(axis).len();
|
||||||
self.extent_len[axis as usize] = Some(len);
|
self.own.region_len[axis as usize] = Some(len);
|
||||||
len
|
len
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,10 +373,10 @@ impl<'a> Painter<'a> {
|
|||||||
/// fraction it or anything under it declares is a fraction of. A
|
/// fraction it or anything under it declares is a fraction of. A
|
||||||
/// container reads it to hand a length of it down -- padding, which
|
/// container reads it to hand a length of it down -- padding, which
|
||||||
/// takes its pixels off. Reading it pins the drawing to that frame, the
|
/// takes its pixels off. Reading it pins the drawing to that frame, the
|
||||||
/// way [`Self::extent_len`] pins it to the box.
|
/// way [`Self::region_len`] pins it to the box.
|
||||||
pub fn frame_len(&mut self, axis: Axis) -> Len {
|
pub fn frame_len(&mut self, axis: Axis) -> Len {
|
||||||
let len = self.frame.axis(axis);
|
let len = self.frame.axis(axis);
|
||||||
self.frame_own_len[axis as usize] = Some(len);
|
self.own.frame_len[axis as usize] = Some(len);
|
||||||
len
|
len
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,13 +414,13 @@ impl<'a> Painter<'a> {
|
|||||||
/// One axis of this widget's own box in pixels. Prefer this to
|
/// One axis of this widget's own box in pixels. Prefer this to
|
||||||
/// [`Self::px_size`] when the other axis cannot affect the drawing.
|
/// [`Self::px_size`] when the other axis cannot affect the drawing.
|
||||||
pub fn px_len(&mut self, axis: Axis) -> Px {
|
pub fn px_len(&mut self, axis: Axis) -> Px {
|
||||||
let part = self.extent.axis(axis).len();
|
let len = self.region.axis(axis).len();
|
||||||
let len = part.to_px(self.window.axis(axis));
|
let px = len.to_px(self.window.axis(axis));
|
||||||
let own = &mut self.extent_own[axis as usize];
|
let own = &mut self.own.region[axis as usize];
|
||||||
if *own == Holds::ANY {
|
if *own == Holds::ANY {
|
||||||
*own = Holds::at(len);
|
*own = Holds::at(px);
|
||||||
}
|
}
|
||||||
len
|
px
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lengths of this widget's own box on `axis` that what it is drawing
|
/// The lengths of this widget's own box on `axis` that what it is drawing
|
||||||
@@ -433,15 +428,15 @@ impl<'a> Painter<'a> {
|
|||||||
/// of the box, and the same reported size. A widget that read its length
|
/// of the box, and the same reported size. A widget that read its length
|
||||||
/// in pixels holds for that one alone until it says otherwise.
|
/// in pixels holds for that one alone until it says otherwise.
|
||||||
pub fn holds(&mut self, axis: Axis, holds: impl Into<Holds>) {
|
pub fn holds(&mut self, axis: Axis, holds: impl Into<Holds>) {
|
||||||
let part = self.extent.axis(axis).len();
|
let len = self.region.axis(axis).len();
|
||||||
let holds = holds.into();
|
let holds = holds.into();
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
holds.contains(part.to_px(self.window.axis(axis))),
|
holds.contains(len.to_px(self.window.axis(axis))),
|
||||||
"'{}' ({:?}) says its drawing holds for lengths that leave out its own box",
|
"'{}' ({:?}) says its drawing holds for lengths that leave out its own box",
|
||||||
self.label(),
|
self.label(),
|
||||||
self.id
|
self.id
|
||||||
);
|
);
|
||||||
self.extent_own[axis as usize] = holds;
|
self.own.region[axis as usize] = holds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A window length in pixels, which is what every length in layout is
|
/// A window length in pixels, which is what every length in layout is
|
||||||
@@ -451,7 +446,7 @@ impl<'a> Painter<'a> {
|
|||||||
pub fn to_px(&mut self, len: Len, axis: Axis) -> Px {
|
pub fn to_px(&mut self, len: Len, axis: Axis) -> Px {
|
||||||
let window = self.window.axis(axis);
|
let window = self.window.axis(axis);
|
||||||
if len.rel != Rel::ZERO {
|
if len.rel != Rel::ZERO {
|
||||||
let own = &mut self.window_own[axis as usize];
|
let own = &mut self.own.window[axis as usize];
|
||||||
if *own == Holds::ANY {
|
if *own == Holds::ANY {
|
||||||
*own = Holds::at(window);
|
*own = Holds::at(window);
|
||||||
}
|
}
|
||||||
@@ -471,7 +466,7 @@ impl<'a> Painter<'a> {
|
|||||||
self.label(),
|
self.label(),
|
||||||
self.id
|
self.id
|
||||||
);
|
);
|
||||||
self.window_own[axis as usize] = holds;
|
self.own.window[axis as usize] = holds;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_data(&mut self) -> &mut TextData {
|
pub fn text_data(&mut self) -> &mut TextData {
|
||||||
@@ -568,7 +563,7 @@ impl Painter<'_> {
|
|||||||
/// is what reached the child; where only pixels did, no length of this
|
/// is what reached the child; where only pixels did, no length of this
|
||||||
/// frame can change the child's and the pin stops here.
|
/// frame can change the child's and the pin stops here.
|
||||||
///
|
///
|
||||||
/// Extent validity maps back through the part of this widget's box,
|
/// A child's validity maps back through the part of this widget's box,
|
||||||
/// where the box the child was asked in is that part; a declared length
|
/// where the box the child was asked in is that part; a declared length
|
||||||
/// places the box inside the part instead, and then only that length
|
/// places the box inside the part instead, and then only that length
|
||||||
/// reaches the child. A narrowed frame is not one of these: it decides
|
/// reaches the child. A narrowed frame is not one of these: it decides
|
||||||
@@ -577,7 +572,7 @@ impl Painter<'_> {
|
|||||||
fn in_parent(
|
fn in_parent(
|
||||||
&self,
|
&self,
|
||||||
holds: LayoutHolds,
|
holds: LayoutHolds,
|
||||||
extent: UiRegion,
|
region: UiRegion,
|
||||||
place: [Place; 2],
|
place: [Place; 2],
|
||||||
narrow: [Option<Len>; 2],
|
narrow: [Option<Len>; 2],
|
||||||
declared: [Option<LayoutLen>; 2],
|
declared: [Option<LayoutLen>; 2],
|
||||||
@@ -600,8 +595,8 @@ impl Painter<'_> {
|
|||||||
// wherever the part is the whole of it, and pins the same
|
// wherever the part is the whole of it, and pins the same
|
||||||
// way.
|
// way.
|
||||||
(Part::All, false) => {
|
(Part::All, false) => {
|
||||||
result.extent[n] = holds.extent[n];
|
result.region[n] = holds.region[n];
|
||||||
result.extent_len[n] = holds.extent_len[n];
|
result.region_len[n] = holds.region_len[n];
|
||||||
}
|
}
|
||||||
// Its box is a part of this widget's own box, in that box's
|
// 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
|
// own lengths, so what it holds for maps back through that
|
||||||
@@ -612,10 +607,10 @@ impl Painter<'_> {
|
|||||||
// widget's own length.
|
// widget's own length.
|
||||||
(Part::Of(span), false) => {
|
(Part::Of(span), false) => {
|
||||||
let part_len = span.len();
|
let part_len = span.len();
|
||||||
result.extent[n] = holds.extent[n].through(part_len);
|
result.region[n] = holds.region[n].through(part_len);
|
||||||
result.extent_len[n] = holds.extent_len[n].map(|pinned| match part_len.rel {
|
result.region_len[n] = holds.region_len[n].map(|pinned| match part_len.rel {
|
||||||
Rel::ONE => pinned - Len::from_parts(Rel::ZERO, part_len.px),
|
Rel::ONE => pinned - Len::from_parts(Rel::ZERO, part_len.px),
|
||||||
_ => self.extent.axis(axis).len(),
|
_ => self.region.axis(axis).len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Its box is a length this widget decided, from its own
|
// Its box is a length this widget decided, from its own
|
||||||
@@ -624,7 +619,7 @@ impl Painter<'_> {
|
|||||||
// on the window and none of it on that box.
|
// on the window and none of it on that box.
|
||||||
_ => {
|
_ => {
|
||||||
result.window[n] =
|
result.window[n] =
|
||||||
result.window[n].and(holds.extent[n].through(extent.axis(axis).len()));
|
result.window[n].and(holds.region[n].through(region.axis(axis).len()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -672,14 +667,14 @@ pub(crate) fn fills(reported: LayoutLen, declared: Option<LayoutLen>, decided: b
|
|||||||
/// That is what makes a fraction the same fraction wherever the part it is
|
/// That is what makes a fraction the same fraction wherever the part it is
|
||||||
/// placed in sits and however long it is -- the fraction is resolved once,
|
/// placed in sits and however long it is -- the fraction is resolved once,
|
||||||
/// here, against the frame it was reported of.
|
/// here, against the frame it was reported of.
|
||||||
pub(crate) fn placed_extent(
|
pub(crate) fn placement(
|
||||||
part: UiRegion,
|
region: UiRegion,
|
||||||
size: Size,
|
size: Size,
|
||||||
declared: [Option<LayoutLen>; 2],
|
declared: [Option<LayoutLen>; 2],
|
||||||
fill: [bool; 2],
|
fill: [bool; 2],
|
||||||
align: RegionAlign,
|
align: RegionAlign,
|
||||||
) -> UiRegion {
|
) -> UiRegion {
|
||||||
let mut placed = part;
|
let mut placed = region;
|
||||||
for axis in AXES {
|
for axis in AXES {
|
||||||
let n = axis as usize;
|
let n = axis as usize;
|
||||||
let reported = size.axis(axis);
|
let reported = size.axis(axis);
|
||||||
@@ -705,7 +700,7 @@ pub(crate) fn placed_extent(
|
|||||||
/// can name. The child's declaration is a fraction of whichever reached it,
|
/// 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
|
/// and is the only one of the three that also places the box: a box the
|
||||||
/// caller decided is what `place` names.
|
/// caller decided is what `place` names.
|
||||||
pub(crate) fn frame_and_extent(
|
pub(crate) fn frame_and_region(
|
||||||
own: UiRegion,
|
own: UiRegion,
|
||||||
parent_frame: UiVec2,
|
parent_frame: UiVec2,
|
||||||
place: [Place; 2],
|
place: [Place; 2],
|
||||||
@@ -713,9 +708,9 @@ pub(crate) fn frame_and_extent(
|
|||||||
declared: [Option<LayoutLen>; 2],
|
declared: [Option<LayoutLen>; 2],
|
||||||
align: RegionAlign,
|
align: RegionAlign,
|
||||||
) -> (UiVec2, UiRegion) {
|
) -> (UiVec2, UiRegion) {
|
||||||
let part = part_of(own, place, align);
|
let given = region_of(own, place, align);
|
||||||
let mut frame = parent_frame;
|
let mut frame = parent_frame;
|
||||||
let mut extent = part;
|
let mut region = given;
|
||||||
for axis in AXES {
|
for axis in AXES {
|
||||||
let n = axis as usize;
|
let n = axis as usize;
|
||||||
let sized = match place[n].part() {
|
let sized = match place[n].part() {
|
||||||
@@ -730,22 +725,22 @@ pub(crate) fn frame_and_extent(
|
|||||||
.unwrap_or(base);
|
.unwrap_or(base);
|
||||||
*frame.axis_mut(axis) = len;
|
*frame.axis_mut(axis) = len;
|
||||||
if declared[n].is_some() {
|
if declared[n].is_some() {
|
||||||
let slot = part.axis(axis);
|
let slot = given.axis(axis);
|
||||||
let start = slot.start + (slot.len() - len).scale(align.axis(axis).rel());
|
let start = slot.start + (slot.len() - len).scale(align.axis(axis).rel());
|
||||||
*extent.axis_mut(axis) = UiSpan::new(start, start + len);
|
*region.axis_mut(axis) = UiSpan::new(start, start + len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(frame, extent)
|
(frame, region)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The part of a widget's own box a `place` names, in the coordinates that
|
/// The part of a widget's own box a `place` names, in the coordinates that
|
||||||
/// box is in.
|
/// box is in.
|
||||||
fn part_of(extent: UiRegion, place: [Place; 2], align: RegionAlign) -> UiRegion {
|
fn region_of(own: UiRegion, place: [Place; 2], align: RegionAlign) -> UiRegion {
|
||||||
let mut part = extent;
|
let mut region = own;
|
||||||
for axis in AXES {
|
for axis in AXES {
|
||||||
*part.axis_mut(axis) = place[axis as usize]
|
*region.axis_mut(axis) = place[axis as usize]
|
||||||
.part()
|
.part()
|
||||||
.of(*extent.axis(axis), align.axis(axis));
|
.of(*own.axis(axis), align.axis(axis));
|
||||||
}
|
}
|
||||||
part
|
region
|
||||||
}
|
}
|
||||||
@@ -27,14 +27,14 @@ pub enum Part {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Part {
|
impl Part {
|
||||||
/// Where it lands in the coordinates `extent` is in.
|
/// Where it lands in the coordinates `own` is in.
|
||||||
pub(crate) fn of(self, extent: UiSpan, align: AxisAlign) -> UiSpan {
|
pub(crate) fn of(self, own: UiSpan, align: AxisAlign) -> UiSpan {
|
||||||
match self {
|
match self {
|
||||||
Self::All => extent,
|
Self::All => own,
|
||||||
Self::From(span) => UiSpan::new(extent.start + span.start, extent.start + span.end),
|
Self::From(span) => UiSpan::new(own.start + span.start, own.start + span.end),
|
||||||
Self::Of(span) => span.within(&extent),
|
Self::Of(span) => span.within(&own),
|
||||||
Self::Sized(len) => {
|
Self::Sized(len) => {
|
||||||
let start = extent.start + (extent.len() - len).scale(align.rel());
|
let start = own.start + (own.len() - len).scale(align.rel());
|
||||||
UiSpan::new(start, start + len)
|
UiSpan::new(start, start + len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-94
@@ -1,10 +1,10 @@
|
|||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
||||||
use crate::ui::painter::{declared_lens, frame_and_extent, placed_extent};
|
use crate::ui::painter::{declared_lens, frame_and_region, placement};
|
||||||
use crate::{
|
use crate::{
|
||||||
ActiveData, Axis, DrawLayers, Holds, IdLike, LayoutHolds, LayoutLen, Len, MaskIdx, MoveIdx,
|
ActiveData, Axis, DrawLayers, IdLike, LayoutHolds, LayoutLen, Len, MaskIdx, MoveIdx, Moves,
|
||||||
Moves, Painter, Part, PixelRegion, Place, PxVec2, Rel, Size, StrongWidget, UiRegion, UiRsc,
|
Painter, Part, PixelRegion, Place, PxVec2, Rel, Size, StrongWidget, UiRegion, UiRsc, UiSpan,
|
||||||
UiSpan, UiVec2, Weight, WidgetId, Widgets,
|
UiVec2, Weight, WidgetId, Widgets,
|
||||||
util::{HashMap, Vec2},
|
util::{HashMap, Vec2},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ pub(super) struct DrawInfo {
|
|||||||
pub frame: UiVec2,
|
pub frame: UiVec2,
|
||||||
/// The box the widget is asked in, in its parent region node's
|
/// The box the widget is asked in, in its parent region node's
|
||||||
/// coordinates.
|
/// coordinates.
|
||||||
pub part: UiRegion,
|
pub region: UiRegion,
|
||||||
/// Where the widget is put, and where it was asked, as parts of the
|
/// 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 [`Place`]. The two are one ask's place until the
|
||||||
/// parent puts the answer somewhere else.
|
/// parent puts the answer somewhere else.
|
||||||
@@ -52,7 +52,7 @@ impl DrawInfo {
|
|||||||
/// drawing is in, and what else one ask of a child is decided from.
|
/// drawing is in, and what else one ask of a child is decided from.
|
||||||
pub(super) struct Placing {
|
pub(super) struct Placing {
|
||||||
pub id: WidgetId,
|
pub id: WidgetId,
|
||||||
pub extent: UiRegion,
|
pub region: UiRegion,
|
||||||
pub frame: UiVec2,
|
pub frame: UiVec2,
|
||||||
pub window: PxVec2,
|
pub window: PxVec2,
|
||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
@@ -125,8 +125,8 @@ impl UiRenderState {
|
|||||||
// it will ask either again.
|
// it will ask either again.
|
||||||
let answer = active
|
let answer = active
|
||||||
.answer
|
.answer
|
||||||
.is_some_and(|(_, holds)| holds.contains(size, active.frame, active.part));
|
.is_some_and(|(_, holds)| holds.contains(size, active.frame, active.region));
|
||||||
answer && active.holds.contains(size, active.frame, active.part)
|
answer && active.holds.contains(size, active.frame, active.region)
|
||||||
});
|
});
|
||||||
if !stands {
|
if !stands {
|
||||||
widgets.needs_redraw.insert(root);
|
widgets.needs_redraw.insert(root);
|
||||||
@@ -135,7 +135,7 @@ impl UiRenderState {
|
|||||||
|
|
||||||
/// The root is asked about in the output. Its own rules narrow both its
|
/// The root is asked about in the output. Its own rules narrow both its
|
||||||
/// frame and box; nothing above it chose a different one.
|
/// frame and box; nothing above it chose a different one.
|
||||||
fn root_info(&self, frame: UiVec2, extent: UiRegion) -> DrawInfo {
|
fn root_info(&self, frame: UiVec2, region: UiRegion) -> DrawInfo {
|
||||||
let px = frame.to_px(self.output_size);
|
let px = frame.to_px(self.output_size);
|
||||||
DrawInfo {
|
DrawInfo {
|
||||||
layer: 0,
|
layer: 0,
|
||||||
@@ -145,7 +145,7 @@ impl UiRenderState {
|
|||||||
region_node: false,
|
region_node: false,
|
||||||
mask: MaskIdx::NONE,
|
mask: MaskIdx::NONE,
|
||||||
frame,
|
frame,
|
||||||
part: extent,
|
region,
|
||||||
placed: [Place::Within(Part::All); 2],
|
placed: [Place::Within(Part::All); 2],
|
||||||
asked: [Place::Within(Part::All); 2],
|
asked: [Place::Within(Part::All); 2],
|
||||||
narrow: [None; 2],
|
narrow: [None; 2],
|
||||||
@@ -196,8 +196,8 @@ impl UiRenderState {
|
|||||||
let _layout = diag::timer(TimerKind::FullLayout);
|
let _layout = diag::timer(TimerKind::FullLayout);
|
||||||
self.clear(rsc);
|
self.clear(rsc);
|
||||||
if let Some(id) = root {
|
if let Some(id) = root {
|
||||||
let (frame, extent) = Self::root_layout(id.id(), rsc.widgets());
|
let (frame, region) = Self::root_layout(id.id(), rsc.widgets());
|
||||||
let info = self.root_info(frame, extent);
|
let info = self.root_info(frame, region);
|
||||||
self.draw_inner(id.id(), info, None, rsc);
|
self.draw_inner(id.id(), info, None, rsc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ impl UiRenderState {
|
|||||||
/// rules. Nothing above it narrowed anything or chose where it goes, so
|
/// rules. Nothing above it narrowed anything or chose where it goes, so
|
||||||
/// its declaration is the whole of what decides either.
|
/// its declaration is the whole of what decides either.
|
||||||
fn root_layout(id: WidgetId, widgets: &Widgets) -> (UiVec2, UiRegion) {
|
fn root_layout(id: WidgetId, widgets: &Widgets) -> (UiVec2, UiRegion) {
|
||||||
frame_and_extent(
|
frame_and_region(
|
||||||
UiRegion::FULL,
|
UiRegion::FULL,
|
||||||
UiVec2::FULL_SIZE,
|
UiVec2::FULL_SIZE,
|
||||||
[Place::Within(Part::All); 2],
|
[Place::Within(Part::All); 2],
|
||||||
@@ -227,11 +227,11 @@ impl UiRenderState {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.or_else(|| self.active.get(&id))
|
.or_else(|| self.active.get(&id))
|
||||||
.and_then(|a| a.parent);
|
.and_then(|a| a.parent);
|
||||||
let part = info.part;
|
let region = info.region;
|
||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
{
|
{
|
||||||
diag::bump(Counter::DrawRequests);
|
diag::bump(Counter::DrawRequests);
|
||||||
diag::draw_request(id, info.parent, part, info.px, info.region_node);
|
diag::draw_request(id, info.parent, region, info.px, info.region_node);
|
||||||
}
|
}
|
||||||
let align = rsc.widgets().alignment(id);
|
let align = rsc.widgets().alignment(id);
|
||||||
let declared = declared_lens(rsc.widgets(), id);
|
let declared = declared_lens(rsc.widgets(), id);
|
||||||
@@ -245,23 +245,24 @@ impl UiRenderState {
|
|||||||
// an answer is kept only with the drawing that gave it, and both
|
// an answer is kept only with the drawing that gave it, and both
|
||||||
// have to hold for the box asked about.
|
// have to hold for the box asked about.
|
||||||
let reused = (!stale)
|
let reused = (!stale)
|
||||||
.then(|| self.retained_answer(id, part, info))
|
.then(|| self.retained_answer(id, region, info))
|
||||||
.flatten()
|
.flatten()
|
||||||
.and_then(|answer| {
|
.and_then(|answer| {
|
||||||
let extent = placed_extent(part, answer.0, declared, info.fill(), align);
|
let placed = placement(region, answer.0, declared, info.fill(), align);
|
||||||
self.try_reuse(id, part, extent, info, rsc).map(|()| answer)
|
self.try_reuse(id, region, placed, info, rsc)
|
||||||
|
.map(|()| answer)
|
||||||
});
|
});
|
||||||
let answer = reused.unwrap_or_else(|| {
|
let answer = reused.unwrap_or_else(|| {
|
||||||
if old.is_none() {
|
if old.is_none() {
|
||||||
old = self.remove(id, false, rsc);
|
old = self.remove(id, false, rsc);
|
||||||
}
|
}
|
||||||
let answer = self.draw_at(id, part, info, old.take(), rsc);
|
let answer = self.draw_at(id, region, info, old.take(), rsc);
|
||||||
// Where the drawing goes: the part its parent gave it, with the
|
// Where the drawing goes: the part its parent gave it, with the
|
||||||
// answer placed inside that part on any axis the parent left
|
// answer placed inside that part on any axis the parent left
|
||||||
// open.
|
// open.
|
||||||
let extent = placed_extent(part, answer.0, declared, info.fill(), align);
|
let placed = placement(region, answer.0, declared, info.fill(), align);
|
||||||
if extent != part {
|
if placed != region {
|
||||||
self.relocate(id, extent, info, rsc);
|
self.relocate(id, placed, info, rsc);
|
||||||
}
|
}
|
||||||
answer
|
answer
|
||||||
});
|
});
|
||||||
@@ -276,7 +277,7 @@ impl UiRenderState {
|
|||||||
active.re_asked = info.re_asked;
|
active.re_asked = info.re_asked;
|
||||||
active.answer = Some(answer);
|
active.answer = Some(answer);
|
||||||
active.asked = info.asked;
|
active.asked = info.asked;
|
||||||
active.part = part;
|
active.region = region;
|
||||||
active.placed = info.placed;
|
active.placed = info.placed;
|
||||||
active.own_align = align;
|
active.own_align = align;
|
||||||
// The previous parent must stop owning the subtree before it can
|
// The previous parent must stop owning the subtree before it can
|
||||||
@@ -291,27 +292,27 @@ impl UiRenderState {
|
|||||||
(answer.0, answer.1, drawing_holds)
|
(answer.0, answer.1, drawing_holds)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls a widget's `draw` and keeps what it drew in `extent` of `frame`.
|
/// Calls a widget's `draw` and keeps what it drew in `region` of `frame`.
|
||||||
fn draw_at(
|
fn draw_at(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: WidgetId,
|
id: WidgetId,
|
||||||
extent: UiRegion,
|
region: UiRegion,
|
||||||
info: DrawInfo,
|
info: DrawInfo,
|
||||||
old: Option<ActiveData>,
|
old: Option<ActiveData>,
|
||||||
rsc: &mut dyn UiRsc,
|
rsc: &mut dyn UiRsc,
|
||||||
) -> (Size, LayoutHolds) {
|
) -> (Size, LayoutHolds) {
|
||||||
let frame = info.frame;
|
let frame = info.frame;
|
||||||
let (move_idx, extent, retired_move) = match info.region_node {
|
let (move_idx, region, retired_move) = match info.region_node {
|
||||||
// A node entry is only a translation. Its local box keeps the
|
// A node entry is only a translation. Its local box keeps the
|
||||||
// same window-unit length as the box in its parent's node.
|
// same window-unit length as the box in its parent's node.
|
||||||
true => (
|
true => (
|
||||||
self.move_slot(id, info.parent_move, translation(extent)),
|
self.move_slot(id, info.parent_move, translation(region)),
|
||||||
local_region(extent),
|
local_region(region),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
// Keep the old entry alive until every descendant has migrated.
|
// Keep the old entry alive until every descendant has migrated.
|
||||||
// Reusing its index sooner could make an old parent look current.
|
// Reusing its index sooner could make an old parent look current.
|
||||||
false => (info.parent_move, extent, self.slots.remove(&id)),
|
false => (info.parent_move, region, self.slots.remove(&id)),
|
||||||
};
|
};
|
||||||
let mask_slot = old
|
let mask_slot = old
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -324,8 +325,7 @@ impl UiRenderState {
|
|||||||
let mut painter = Painter {
|
let mut painter = Painter {
|
||||||
state: self,
|
state: self,
|
||||||
frame,
|
frame,
|
||||||
extent,
|
region,
|
||||||
extent_len: [None; 2],
|
|
||||||
window,
|
window,
|
||||||
mask: info.mask,
|
mask: info.mask,
|
||||||
layer: info.layer,
|
layer: info.layer,
|
||||||
@@ -337,10 +337,8 @@ impl UiRenderState {
|
|||||||
mask_slot,
|
mask_slot,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
size_deps: Vec::new(),
|
size_deps: Vec::new(),
|
||||||
window_own: [Holds::ANY; 2],
|
own: LayoutHolds::ANY,
|
||||||
frame_own_len: [None; 2],
|
|
||||||
under: Vec::new(),
|
under: Vec::new(),
|
||||||
extent_own: [Holds::ANY; 2],
|
|
||||||
answer_under: LayoutHolds::ANY,
|
answer_under: LayoutHolds::ANY,
|
||||||
depth: info.depth,
|
depth: info.depth,
|
||||||
move_idx,
|
move_idx,
|
||||||
@@ -362,20 +360,17 @@ impl UiRenderState {
|
|||||||
state: _,
|
state: _,
|
||||||
rsc: _,
|
rsc: _,
|
||||||
frame: _,
|
frame: _,
|
||||||
extent: _,
|
region: _,
|
||||||
window: _,
|
window: _,
|
||||||
mask,
|
mask,
|
||||||
textures,
|
textures,
|
||||||
primitives,
|
primitives,
|
||||||
mask_region,
|
mask_region,
|
||||||
mask_slot,
|
mask_slot,
|
||||||
extent_own,
|
own,
|
||||||
extent_len,
|
|
||||||
answer_under,
|
answer_under,
|
||||||
children,
|
children,
|
||||||
size_deps,
|
size_deps,
|
||||||
window_own,
|
|
||||||
frame_own_len,
|
|
||||||
under,
|
under,
|
||||||
move_idx,
|
move_idx,
|
||||||
layer,
|
layer,
|
||||||
@@ -418,7 +413,7 @@ impl UiRenderState {
|
|||||||
mask == info.mask
|
mask == info.mask
|
||||||
|| AXES
|
|| AXES
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.all(|axis| within_box(size, extent, self.output_size, axis)),
|
.all(|axis| within_box(size, region, self.output_size, axis)),
|
||||||
"'{}' ({id:?}) clips to {px:?} and reports {size}",
|
"'{}' ({id:?}) clips to {px:?} and reports {size}",
|
||||||
rsc.widgets().label(id),
|
rsc.widgets().label(id),
|
||||||
);
|
);
|
||||||
@@ -444,21 +439,16 @@ impl UiRenderState {
|
|||||||
.is_some_and(|len| len.rel != Rel::ZERO);
|
.is_some_and(|len| len.rel != Rel::ZERO);
|
||||||
match fraction {
|
match fraction {
|
||||||
true => Some(info.frame.axis(axis)),
|
true => Some(info.frame.axis(axis)),
|
||||||
false => frame_own_len[axis as usize],
|
false => own.frame_len[axis as usize],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let own_holds = LayoutHolds {
|
let own_holds = LayoutHolds { frame_len, ..own };
|
||||||
window: window_own,
|
|
||||||
frame_len,
|
|
||||||
extent: extent_own,
|
|
||||||
extent_len,
|
|
||||||
};
|
|
||||||
let answer_holds = own_holds.and(answer_under);
|
let answer_holds = own_holds.and(answer_under);
|
||||||
let holds = under
|
let holds = under
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.fold(answer_holds, |holds, (_, child)| holds.and(child));
|
.fold(answer_holds, |holds, (_, child)| holds.and(child));
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
holds.contains(self.output_size, info.frame, extent),
|
holds.contains(self.output_size, info.frame, region),
|
||||||
"'{}' ({id:?}) drew in {px:?}, outside the ranges it reported: {holds:?}",
|
"'{}' ({id:?}) drew in {px:?}, outside the ranges it reported: {holds:?}",
|
||||||
rsc.widgets().label(id),
|
rsc.widgets().label(id),
|
||||||
);
|
);
|
||||||
@@ -477,7 +467,7 @@ impl UiRenderState {
|
|||||||
region_node: false,
|
region_node: false,
|
||||||
mask,
|
mask,
|
||||||
frame: UiVec2::FULL_SIZE,
|
frame: UiVec2::FULL_SIZE,
|
||||||
part: UiRegion::FULL,
|
region: UiRegion::FULL,
|
||||||
placed: [Place::Within(Part::All); 2],
|
placed: [Place::Within(Part::All); 2],
|
||||||
asked: [Place::Within(Part::All); 2],
|
asked: [Place::Within(Part::All); 2],
|
||||||
narrow: [None; 2],
|
narrow: [None; 2],
|
||||||
@@ -492,12 +482,12 @@ impl UiRenderState {
|
|||||||
|
|
||||||
let active = ActiveData {
|
let active = ActiveData {
|
||||||
id,
|
id,
|
||||||
extent,
|
placement: region,
|
||||||
frame: info.frame,
|
frame: info.frame,
|
||||||
narrow: info.narrow,
|
narrow: info.narrow,
|
||||||
placed: info.placed,
|
placed: info.placed,
|
||||||
asked: info.asked,
|
asked: info.asked,
|
||||||
part: extent,
|
region,
|
||||||
// Whoever asked writes the answer.
|
// Whoever asked writes the answer.
|
||||||
answer: None,
|
answer: None,
|
||||||
re_asked: info.re_asked,
|
re_asked: info.re_asked,
|
||||||
@@ -551,7 +541,7 @@ impl UiRenderState {
|
|||||||
fn retained_answer(
|
fn retained_answer(
|
||||||
&self,
|
&self,
|
||||||
id: WidgetId,
|
id: WidgetId,
|
||||||
part: UiRegion,
|
region: UiRegion,
|
||||||
info: DrawInfo,
|
info: DrawInfo,
|
||||||
) -> Option<(Size, LayoutHolds)> {
|
) -> Option<(Size, LayoutHolds)> {
|
||||||
let active = self.active.get(&id)?;
|
let active = self.active.get(&id)?;
|
||||||
@@ -565,17 +555,17 @@ impl UiRenderState {
|
|||||||
let answer = active.answer?;
|
let answer = active.answer?;
|
||||||
answer
|
answer
|
||||||
.1
|
.1
|
||||||
.contains(self.output_size, info.frame, part)
|
.contains(self.output_size, info.frame, region)
|
||||||
.then_some(answer)
|
.then_some(answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Keeps the retained drawing if its contract holds for `part`, the box
|
/// Keeps the retained drawing if its contract holds for `part`, the box
|
||||||
/// asked about, and puts it at `extent`, where the answer places it.
|
/// asked about, and puts it at `placed`, where the answer places it.
|
||||||
fn try_reuse(
|
fn try_reuse(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: WidgetId,
|
id: WidgetId,
|
||||||
part: UiRegion,
|
region: UiRegion,
|
||||||
extent: UiRegion,
|
placed: UiRegion,
|
||||||
info: DrawInfo,
|
info: DrawInfo,
|
||||||
rsc: &mut dyn UiRsc,
|
rsc: &mut dyn UiRsc,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
@@ -630,7 +620,7 @@ impl UiRenderState {
|
|||||||
// In pixels, because the box is a fraction of the window and that
|
// In pixels, because the box is a fraction of the window and that
|
||||||
// may be what changed -- an unchanged fraction of a window half the
|
// may be what changed -- an unchanged fraction of a window half the
|
||||||
// size is half the widget.
|
// size is half the widget.
|
||||||
if !active.holds.contains(self.output_size, info.frame, part) {
|
if !active.holds.contains(self.output_size, info.frame, region) {
|
||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
{
|
{
|
||||||
// Which of the three said no, so a frame that redraws more
|
// Which of the three said no, so a frame that redraws more
|
||||||
@@ -639,7 +629,7 @@ impl UiRenderState {
|
|||||||
let holds = active.holds;
|
let holds = active.holds;
|
||||||
for axis in AXES {
|
for axis in AXES {
|
||||||
let n = axis as usize;
|
let n = axis as usize;
|
||||||
if holds.extent_len[n].is_some_and(|pinned| pinned != part.axis(axis).len()) {
|
if holds.region_len[n].is_some_and(|pinned| pinned != region.axis(axis).len()) {
|
||||||
diag::bump(Counter::OutsidePinnedLen);
|
diag::bump(Counter::OutsidePinnedLen);
|
||||||
}
|
}
|
||||||
if !holds.window[n].contains(self.output_size.axis(axis))
|
if !holds.window[n].contains(self.output_size.axis(axis))
|
||||||
@@ -647,10 +637,10 @@ impl UiRenderState {
|
|||||||
{
|
{
|
||||||
diag::bump(Counter::OutsideFrame);
|
diag::bump(Counter::OutsideFrame);
|
||||||
}
|
}
|
||||||
if !holds.extent[n]
|
if !holds.region[n]
|
||||||
.contains(part.axis(axis).len().to_px(self.output_size.axis(axis)))
|
.contains(region.axis(axis).len().to_px(self.output_size.axis(axis)))
|
||||||
{
|
{
|
||||||
diag::bump(Counter::OutsideExtent);
|
diag::bump(Counter::OutsideRegion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diag::bump(Counter::ReuseOutside);
|
diag::bump(Counter::ReuseOutside);
|
||||||
@@ -658,14 +648,14 @@ impl UiRenderState {
|
|||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.relocate(id, extent, info, rsc);
|
self.relocate(id, placed, info, rsc);
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Puts a retained drawing where its parent now has it, without drawing:
|
/// Puts a retained drawing where its parent now has it, without drawing:
|
||||||
/// a widget with a node of its own writes that node's translation, and
|
/// a widget with a node of its own writes that node's translation, and
|
||||||
/// one without re-expresses its own drawing and everything inside it.
|
/// one without re-expresses its own drawing and everything inside it.
|
||||||
fn relocate(&mut self, id: WidgetId, extent: UiRegion, info: DrawInfo, rsc: &mut dyn UiRsc) {
|
fn relocate(&mut self, id: WidgetId, placed: UiRegion, info: DrawInfo, rsc: &mut dyn UiRsc) {
|
||||||
let active = &self.active[&id];
|
let active = &self.active[&id];
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
!rsc.widgets().needs_redraw.contains(&id),
|
!rsc.widgets().needs_redraw.contains(&id),
|
||||||
@@ -674,13 +664,13 @@ impl UiRenderState {
|
|||||||
);
|
);
|
||||||
let has_region_node = active.move_idx != active.parent_move;
|
let has_region_node = active.move_idx != active.parent_move;
|
||||||
let local = match has_region_node {
|
let local = match has_region_node {
|
||||||
true => local_region(extent),
|
true => local_region(placed),
|
||||||
false => extent,
|
false => placed,
|
||||||
};
|
};
|
||||||
let moved = active.extent != local;
|
let moved = active.placement != local;
|
||||||
let slot = active.move_idx;
|
let slot = active.move_idx;
|
||||||
if has_region_node {
|
if has_region_node {
|
||||||
self.moves.set(slot, translation(extent));
|
self.moves.set(slot, translation(placed));
|
||||||
}
|
}
|
||||||
if moved {
|
if moved {
|
||||||
self.reposition(id, local, info, rsc);
|
self.reposition(id, local, info, rsc);
|
||||||
@@ -728,9 +718,9 @@ impl UiRenderState {
|
|||||||
rsc: &mut dyn UiRsc,
|
rsc: &mut dyn UiRsc,
|
||||||
) {
|
) {
|
||||||
let active = &self.active[&child];
|
let active = &self.active[&child];
|
||||||
let (frame, part) = Self::ask_again(active, at, place);
|
let (frame, region) = Self::ask_again(active, at, place);
|
||||||
let extent = placed_extent(
|
let placed = placement(
|
||||||
part,
|
region,
|
||||||
active.measured().unwrap_or(active.size),
|
active.measured().unwrap_or(active.size),
|
||||||
active.declared,
|
active.declared,
|
||||||
place.map(Place::fills),
|
place.map(Place::fills),
|
||||||
@@ -744,14 +734,14 @@ impl UiRenderState {
|
|||||||
region_node: active.move_idx != active.parent_move,
|
region_node: active.move_idx != active.parent_move,
|
||||||
mask: at.mask,
|
mask: at.mask,
|
||||||
frame,
|
frame,
|
||||||
part,
|
region,
|
||||||
placed: place,
|
placed: place,
|
||||||
asked: active.asked,
|
asked: active.asked,
|
||||||
narrow: active.narrow,
|
narrow: active.narrow,
|
||||||
re_asked: active.re_asked,
|
re_asked: active.re_asked,
|
||||||
px: frame.to_px(at.window),
|
px: frame.to_px(at.window),
|
||||||
};
|
};
|
||||||
self.relocate(child, extent, info, rsc);
|
self.relocate(child, placed, info, rsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The frame and the box a widget already drawn is given at `place` of
|
/// The frame and the box a widget already drawn is given at `place` of
|
||||||
@@ -759,8 +749,8 @@ impl UiRenderState {
|
|||||||
/// it declared are its own record's, so both are resolved against that
|
/// it declared are its own record's, so both are resolved against that
|
||||||
/// parent's frame again exactly as the first ask resolved them.
|
/// parent's frame 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: [Place; 2]) -> (UiVec2, UiRegion) {
|
||||||
frame_and_extent(
|
frame_and_region(
|
||||||
at.extent,
|
at.region,
|
||||||
at.frame,
|
at.frame,
|
||||||
place,
|
place,
|
||||||
active.narrow,
|
active.narrow,
|
||||||
@@ -773,19 +763,19 @@ impl UiRenderState {
|
|||||||
/// is placed as a part of that box, so each one's new box is its retained
|
/// is placed as a part of that box, so each one's new box is its retained
|
||||||
/// part re-added to the new start -- and a child whose own box then did
|
/// part re-added to the new start -- and a child whose own box then did
|
||||||
/// not change is not touched at all.
|
/// not change is not touched at all.
|
||||||
fn reposition(&mut self, id: WidgetId, extent: UiRegion, info: DrawInfo, rsc: &mut dyn UiRsc) {
|
fn reposition(&mut self, id: WidgetId, placed: UiRegion, info: DrawInfo, rsc: &mut dyn UiRsc) {
|
||||||
let active = self.active.get_mut(&id).unwrap();
|
let active = self.active.get_mut(&id).unwrap();
|
||||||
active.extent = extent;
|
active.placement = placed;
|
||||||
for primitive in &active.primitives {
|
for primitive in &active.primitives {
|
||||||
let handle = &primitive.handle;
|
let handle = &primitive.handle;
|
||||||
*self.layers[handle.layer].region_mut(handle) = primitive.region.within(&extent);
|
*self.layers[handle.layer].region_mut(handle) = primitive.region.within(&placed);
|
||||||
}
|
}
|
||||||
if let Some(mask_region) = active.mask_region {
|
if let Some(mask_region) = active.mask_region {
|
||||||
rsc.ui_mut().masks.get_mut(active.mask).region = mask_region.within(&extent);
|
rsc.ui_mut().masks.get_mut(active.mask).region = mask_region.within(&placed);
|
||||||
}
|
}
|
||||||
let at = Placing {
|
let at = Placing {
|
||||||
id,
|
id,
|
||||||
extent,
|
region: placed,
|
||||||
frame: info.frame,
|
frame: info.frame,
|
||||||
window: self.output_size,
|
window: self.output_size,
|
||||||
depth: info.depth,
|
depth: info.depth,
|
||||||
@@ -890,12 +880,12 @@ impl UiRenderState {
|
|||||||
id,
|
id,
|
||||||
ActiveData {
|
ActiveData {
|
||||||
id,
|
id,
|
||||||
extent: UiRegion::FULL,
|
placement: UiRegion::FULL,
|
||||||
frame: UiVec2::FULL_SIZE,
|
frame: UiVec2::FULL_SIZE,
|
||||||
narrow: [None; 2],
|
narrow: [None; 2],
|
||||||
placed: [Place::Within(Part::All); 2],
|
placed: [Place::Within(Part::All); 2],
|
||||||
asked: [Place::Within(Part::All); 2],
|
asked: [Place::Within(Part::All); 2],
|
||||||
part: UiRegion::FULL,
|
region: UiRegion::FULL,
|
||||||
answer: None,
|
answer: None,
|
||||||
re_asked: false,
|
re_asked: false,
|
||||||
size,
|
size,
|
||||||
@@ -1080,7 +1070,7 @@ impl UiRenderState {
|
|||||||
let active = self.active.get(&id.id())?;
|
let active = self.active.get(&id.id())?;
|
||||||
active.drawn.then(|| {
|
active.drawn.then(|| {
|
||||||
self.moves
|
self.moves
|
||||||
.resolve(active.move_idx, active.extent)
|
.resolve(active.move_idx, active.placement)
|
||||||
.to_px(self.output_size)
|
.to_px(self.output_size)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1122,10 +1112,10 @@ impl UiRenderState {
|
|||||||
// box is its own to work out again against the output. Every other
|
// box is its own to work out again against the output. Every other
|
||||||
// widget was given one.
|
// widget was given one.
|
||||||
let Some(parent) = active.parent else {
|
let Some(parent) = active.parent else {
|
||||||
let (frame, extent) = Self::root_layout(id, rsc.widgets());
|
let (frame, region) = Self::root_layout(id, rsc.widgets());
|
||||||
let info = DrawInfo {
|
let info = DrawInfo {
|
||||||
mask: active.parent_mask,
|
mask: active.parent_mask,
|
||||||
..self.root_info(frame, extent)
|
..self.root_info(frame, region)
|
||||||
};
|
};
|
||||||
#[cfg(feature = "layout-diagnostics")]
|
#[cfg(feature = "layout-diagnostics")]
|
||||||
diag::bump(Counter::LocalRedraws);
|
diag::bump(Counter::LocalRedraws);
|
||||||
@@ -1139,8 +1129,8 @@ impl UiRenderState {
|
|||||||
// draw ran in and what its children's parts are of. Where the
|
// draw ran in and what its children's parts are of. Where the
|
||||||
// parent's answer put its own drawing is not a question anybody
|
// parent's answer put its own drawing is not a question anybody
|
||||||
// asked, and nothing is asked in it here either.
|
// asked, and nothing is asked in it here either.
|
||||||
let parent_at = self.placing_of(parent, self.active[&parent].part);
|
let parent_at = self.placing_of(parent, self.active[&parent].region);
|
||||||
let (frame, part) = Self::ask_again(active, &parent_at, active.asked);
|
let (frame, region) = Self::ask_again(active, &parent_at, active.asked);
|
||||||
let info = DrawInfo {
|
let info = DrawInfo {
|
||||||
layer: active.layer,
|
layer: active.layer,
|
||||||
parent: active.parent,
|
parent: active.parent,
|
||||||
@@ -1149,7 +1139,7 @@ impl UiRenderState {
|
|||||||
region_node: rsc.widgets().is_region_node(id),
|
region_node: rsc.widgets().is_region_node(id),
|
||||||
mask: active.parent_mask,
|
mask: active.parent_mask,
|
||||||
frame,
|
frame,
|
||||||
part,
|
region,
|
||||||
placed: active.asked,
|
placed: active.asked,
|
||||||
asked: active.asked,
|
asked: active.asked,
|
||||||
narrow: active.narrow,
|
narrow: active.narrow,
|
||||||
@@ -1171,7 +1161,7 @@ impl UiRenderState {
|
|||||||
active.answer = was_answer;
|
active.answer = was_answer;
|
||||||
}
|
}
|
||||||
if active.holds.covers(was_holds)
|
if active.holds.covers(was_holds)
|
||||||
&& was_holds.contains(self.output_size, active.frame, active.extent)
|
&& was_holds.contains(self.output_size, active.frame, active.placement)
|
||||||
{
|
{
|
||||||
active.holds = was_holds;
|
active.holds = was_holds;
|
||||||
}
|
}
|
||||||
@@ -1188,20 +1178,20 @@ impl UiRenderState {
|
|||||||
// The answer stands, so where the parent put it stands: the
|
// The answer stands, so where the parent put it stands: the
|
||||||
// fresh drawing goes back there -- the same place, of the box
|
// fresh drawing goes back there -- the same place, of the box
|
||||||
// the parent's answer chose rather than the one it was asked in.
|
// the parent's answer chose rather than the one it was asked in.
|
||||||
let at = self.placing_of(parent, self.active[&parent].extent);
|
let at = self.placing_of(parent, self.active[&parent].placement);
|
||||||
self.place_in(id, &at, was_place, rsc);
|
self.place_in(id, &at, was_place, rsc);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A drawn widget as the thing its children are placed within, with
|
/// A drawn widget as the thing its children are placed within, with
|
||||||
/// `extent` as the box their parts are of: the box it was asked in for
|
/// `region` as the box their parts are of: the box it was asked in for
|
||||||
/// asking one of them again, the box its answer chose for placing one.
|
/// asking one of them again, the box its answer chose for placing one.
|
||||||
fn placing_of(&self, id: WidgetId, extent: UiRegion) -> Placing {
|
fn placing_of(&self, id: WidgetId, region: UiRegion) -> Placing {
|
||||||
let active = &self.active[&id];
|
let active = &self.active[&id];
|
||||||
Placing {
|
Placing {
|
||||||
id,
|
id,
|
||||||
extent,
|
region,
|
||||||
frame: active.frame,
|
frame: active.frame,
|
||||||
window: self.output_size,
|
window: self.output_size,
|
||||||
depth: active.depth,
|
depth: active.depth,
|
||||||
@@ -1215,11 +1205,11 @@ impl UiRenderState {
|
|||||||
/// Both are lengths of the window, so the comparison is in its pixels. A
|
/// Both are lengths of the window, so the comparison is in its pixels. A
|
||||||
/// share is a length only to whoever divides one, so it is not a claim about
|
/// share is a length only to whoever divides one, so it is not a claim about
|
||||||
/// this box and cannot exceed it.
|
/// this box and cannot exceed it.
|
||||||
fn within_box(size: Size, extent: UiRegion, window: PxVec2, axis: Axis) -> bool {
|
fn within_box(size: Size, region: UiRegion, window: PxVec2, axis: Axis) -> bool {
|
||||||
let len = size.axis(axis);
|
let len = size.axis(axis);
|
||||||
let window = window.axis(axis);
|
let window = window.axis(axis);
|
||||||
len.leftover != Weight::ZERO
|
len.leftover != Weight::ZERO
|
||||||
|| Len::from_parts(len.rel, len.px).to_px(window) <= extent.axis(axis).len().to_px(window)
|
|| Len::from_parts(len.rel, len.px).to_px(window) <= region.axis(axis).len().to_px(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box in a fresh region node keeps its window-unit length and starts at
|
/// A box in a fresh region node keeps its window-unit length and starts at
|
||||||
|
|||||||
+1
-1
@@ -134,7 +134,7 @@ impl Widget for Branch {
|
|||||||
};
|
};
|
||||||
painter.window_holds(Axis::X, holds.through(len));
|
painter.window_holds(Axis::X, holds.through(len));
|
||||||
|
|
||||||
let below = Place::Within(Part::From(UiSpan::new(cut, painter.extent_len(Axis::Y))));
|
let below = Place::Within(Part::From(UiSpan::new(cut, painter.region_len(Axis::Y))));
|
||||||
let place = [Place::Within(Part::All), below];
|
let place = [Place::Within(Part::All), below];
|
||||||
match px > threshold {
|
match px > threshold {
|
||||||
true => painter.widget_at(&self.wide, [None; 2], place),
|
true => painter.widget_at(&self.wide, [None; 2], place),
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ impl Widget for Offset {
|
|||||||
// without the offset.
|
// without the offset.
|
||||||
let moved = |len: Len, amt: Len| Place::Within(Part::From(UiSpan::new(amt, len + amt)));
|
let moved = |len: Len, amt: Len| Place::Within(Part::From(UiSpan::new(amt, len + amt)));
|
||||||
let place = [
|
let place = [
|
||||||
moved(painter.extent_len(Axis::X), self.amt.x),
|
moved(painter.region_len(Axis::X), self.amt.x),
|
||||||
moved(painter.extent_len(Axis::Y), self.amt.y),
|
moved(painter.region_len(Axis::Y), self.amt.y),
|
||||||
];
|
];
|
||||||
painter.widget_at(&self.inner, [None; 2], place).size()
|
painter.widget_at(&self.inner, [None; 2], place).size()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ impl Widget for Span {
|
|||||||
// The row: this span's own box, as a length of the frame its children
|
// The row: this span's own box, as a length of the frame its children
|
||||||
// are laid out against. Its start is nothing's business -- a slot is
|
// are laid out against. Its start is nothing's business -- a slot is
|
||||||
// a length from it -- so what this reads is the length alone.
|
// a length from it -- so what this reads is the length alone.
|
||||||
let far = painter.extent_len(axis);
|
let far = painter.region_len(axis);
|
||||||
let along = |from: Len, to: Len| match self.dir.sign {
|
let along = |from: Len, to: Len| match self.dir.sign {
|
||||||
Sign::Pos => UiSpan::new(from, to),
|
Sign::Pos => UiSpan::new(from, to),
|
||||||
Sign::Neg => UiSpan::new(far - to, far - from),
|
Sign::Neg => UiSpan::new(far - to, far - from),
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ impl Widget for BranchesOnMeasurement {
|
|||||||
.len(Axis::X);
|
.len(Axis::X);
|
||||||
let px = painter.to_px(measured.apply_leftover(), Axis::X);
|
let px = painter.to_px(measured.apply_leftover(), Axis::X);
|
||||||
|
|
||||||
let below = Place::Within(Part::From(UiSpan::new(cut, painter.extent_len(Axis::Y))));
|
let below = Place::Within(Part::From(UiSpan::new(cut, painter.region_len(Axis::Y))));
|
||||||
let place = [Place::Within(Part::All), below];
|
let place = [Place::Within(Part::All), below];
|
||||||
match px > Px::from_f32(self.threshold) {
|
match px > Px::from_f32(self.threshold) {
|
||||||
true => painter.widget_at(&self.wide, [None; 2], place),
|
true => painter.widget_at(&self.wide, [None; 2], place),
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ fn padding_keeps_the_frame_distinct_from_the_room_left_in_a_row() {
|
|||||||
h.set_root((icon, padded).span(Dir::RIGHT).width(rel(1.0)));
|
h.set_root((icon, padded).span(Dir::RIGHT).width(rel(1.0)));
|
||||||
let active = &h.render.active[&text.id()];
|
let active = &h.render.active[&text.id()];
|
||||||
let window = h.render.output_size().x;
|
let window = h.render.output_size().x;
|
||||||
let asked = active.part.x.len().to_px(window);
|
let asked = active.region.x.len().to_px(window);
|
||||||
assert_eq!(active.frame.x.to_px(window), Px::from_int(868));
|
assert_eq!(active.frame.x.to_px(window), Px::from_int(868));
|
||||||
assert_eq!(asked, Px::from_int(844));
|
assert_eq!(asked, Px::from_int(844));
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ fn padding_narrows_both_frame_and_box_inside_a_share() {
|
|||||||
let active = &h.render.active[&text.id()];
|
let active = &h.render.active[&text.id()];
|
||||||
let window = h.render.output_size().x;
|
let window = h.render.output_size().x;
|
||||||
assert_eq!(active.frame.x.to_px(window), Px::from_int(418));
|
assert_eq!(active.frame.x.to_px(window), Px::from_int(418));
|
||||||
assert_eq!(active.part.x.len().to_px(window), Px::from_int(418));
|
assert_eq!(active.region.x.len().to_px(window), Px::from_int(418));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -500,7 +500,7 @@ fn a_row_of_equal_shares_fills_it_exactly() {
|
|||||||
/// a step of. Kept in step with `snap_floor` in `prelude.wgsl`.
|
/// a step of. Kept in step with `snap_floor` in `prelude.wgsl`.
|
||||||
fn drawn_edges(h: &Harness, id: WidgetId, axis: Axis) -> (f32, f32) {
|
fn drawn_edges(h: &Harness, id: WidgetId, axis: Axis) -> (f32, f32) {
|
||||||
let active = &h.render.active[&id];
|
let active = &h.render.active[&id];
|
||||||
let region = h.render.moves.resolve(active.move_idx, active.extent);
|
let region = h.render.moves.resolve(active.move_idx, active.placement);
|
||||||
let dim = h.size().axis(axis);
|
let dim = h.size().axis(axis);
|
||||||
let snap = |v: f32| (v + Px::STEP.to_f32() * 0.5).floor();
|
let snap = |v: f32| (v + Px::STEP.to_f32() * 0.5).floor();
|
||||||
let edge = |s: Len| snap(s.rel.to_f32() * dim + s.px.to_f32());
|
let edge = |s: Len| snap(s.rel.to_f32() * dim + s.px.to_f32());
|
||||||
|
|||||||
+27
-27
@@ -797,7 +797,7 @@ fn primitive_bounds(h: &Harness, id: WidgetId) -> Vec<PixelRegion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn changing_an_inherited_extent_keeps_the_original_measurement_offer() {
|
fn changing_an_inherited_region_keeps_the_original_measurement_offer() {
|
||||||
fn build(h: &mut Harness, width: i32, text: &str) -> (WeakWidget<Text>, WeakWidget<Rect>) {
|
fn build(h: &mut Harness, width: i32, text: &str) -> (WeakWidget<Text>, WeakWidget<Rect>) {
|
||||||
let first = rect(Color::RED).width(width).add(&mut h.rsc);
|
let first = rect(Color::RED).width(width).add(&mut h.rsc);
|
||||||
let words = wtext(text).size(20).wrap(true).add(&mut h.rsc);
|
let words = wtext(text).size(20).wrap(true).add(&mut h.rsc);
|
||||||
@@ -959,17 +959,17 @@ fn glyph_origins_compose_identically_when_drawn_and_when_retained() {
|
|||||||
}
|
}
|
||||||
struct Frame {
|
struct Frame {
|
||||||
child: StrongWidget,
|
child: StrongWidget,
|
||||||
|
frame: UiRegion,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
extent: UiRegion,
|
|
||||||
}
|
}
|
||||||
impl Widget for Frame {
|
impl Widget for Frame {
|
||||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||||
painter.widget_at(
|
painter.widget_at(
|
||||||
&self.child,
|
&self.child,
|
||||||
[Some(self.region.x.len()), None],
|
[Some(self.frame.x.len()), None],
|
||||||
[
|
[
|
||||||
Place::Fill(Part::From(self.extent.x)),
|
Place::Fill(Part::From(self.region.x)),
|
||||||
Place::Fill(Part::From(self.extent.y)),
|
Place::Fill(Part::From(self.region.y)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
Size::LEFTOVER
|
Size::LEFTOVER
|
||||||
@@ -986,15 +986,15 @@ fn glyph_origins_compose_identically_when_drawn_and_when_retained() {
|
|||||||
h.rsc.widgets_mut().set_region_node(text, node);
|
h.rsc.widgets_mut().set_region_node(text, node);
|
||||||
let root = Frame {
|
let root = Frame {
|
||||||
child: text.add_strong(&mut h.rsc),
|
child: text.add_strong(&mut h.rsc),
|
||||||
|
frame: UiRegion::FULL,
|
||||||
region: UiRegion::FULL,
|
region: UiRegion::FULL,
|
||||||
extent: UiRegion::FULL,
|
|
||||||
}
|
}
|
||||||
.add(&mut h.rsc);
|
.add(&mut h.rsc);
|
||||||
h.set_root(root);
|
h.set_root(root);
|
||||||
for (start, end) in [(0.13, 0.83), (-0.17, 1.23), (0.31, 0.67)] {
|
for (start, end) in [(0.13, 0.83), (-0.17, 1.23), (0.31, 0.67)] {
|
||||||
let before = draws.get();
|
let before = draws.get();
|
||||||
h.rsc[root].region.x = UiSpan::new(Len::px(13.125), Len::px(287.375));
|
h.rsc[root].frame.x = UiSpan::new(Len::px(13.125), Len::px(287.375));
|
||||||
h.rsc[root].extent = UiRegion::new(
|
h.rsc[root].region = UiRegion::new(
|
||||||
UiSpan::new(Len::rel(start), Len::rel(end)),
|
UiSpan::new(Len::rel(start), Len::rel(end)),
|
||||||
UiSpan::new(Len::px(7.25), Len::rel(end)),
|
UiSpan::new(Len::px(7.25), Len::rel(end)),
|
||||||
);
|
);
|
||||||
@@ -1117,7 +1117,7 @@ fn widening_and_restoring_a_contract_does_not_invalidate_its_reader() {
|
|||||||
assert_eq!(leaf_draws.get(), settled + 1);
|
assert_eq!(leaf_draws.get(), settled + 1);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
fn padding_and_stack_boxes_follow_the_region_without_drawing_again() {
|
||||||
struct Observed<W> {
|
struct Observed<W> {
|
||||||
widget: W,
|
widget: W,
|
||||||
draws: Rc<Cell<usize>>,
|
draws: Rc<Cell<usize>>,
|
||||||
@@ -1130,7 +1130,7 @@ fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
|||||||
}
|
}
|
||||||
struct Frame {
|
struct Frame {
|
||||||
child: StrongWidget,
|
child: StrongWidget,
|
||||||
extent: UiRegion,
|
region: UiRegion,
|
||||||
}
|
}
|
||||||
impl Widget for Frame {
|
impl Widget for Frame {
|
||||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||||
@@ -1138,15 +1138,15 @@ fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
|||||||
&self.child,
|
&self.child,
|
||||||
[None; 2],
|
[None; 2],
|
||||||
[
|
[
|
||||||
Place::Fill(Part::From(self.extent.x)),
|
Place::Fill(Part::From(self.region.x)),
|
||||||
Place::Fill(Part::From(self.extent.y)),
|
Place::Fill(Part::From(self.region.y)),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
Size::LEFTOVER
|
Size::LEFTOVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for node in [false, true] {
|
for node in [false, true] {
|
||||||
let plant = |h: &mut Harness, extent| {
|
let plant = |h: &mut Harness, region| {
|
||||||
let draws = Rc::new(Cell::new(0));
|
let draws = Rc::new(Cell::new(0));
|
||||||
let leaf = rect(Color::BLUE).masked().add(&mut h.rsc);
|
let leaf = rect(Color::BLUE).masked().add(&mut h.rsc);
|
||||||
h.rsc.widgets_mut().set_region_node(leaf, node);
|
h.rsc.widgets_mut().set_region_node(leaf, node);
|
||||||
@@ -1167,7 +1167,7 @@ fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
|||||||
draws: draws.clone(),
|
draws: draws.clone(),
|
||||||
}
|
}
|
||||||
.add_strong(&mut h.rsc);
|
.add_strong(&mut h.rsc);
|
||||||
let root = Frame { child: pad, extent }.add(&mut h.rsc);
|
let root = Frame { child: pad, region }.add(&mut h.rsc);
|
||||||
h.set_root(root);
|
h.set_root(root);
|
||||||
(root, leaf, fixed, draws)
|
(root, leaf, fixed, draws)
|
||||||
};
|
};
|
||||||
@@ -1182,13 +1182,13 @@ fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
|||||||
let mut warm = Harness::new((403, 211));
|
let mut warm = Harness::new((403, 211));
|
||||||
let (root, leaf, fixed, draws) = plant(&mut warm, at(0.13));
|
let (root, leaf, fixed, draws) = plant(&mut warm, at(0.13));
|
||||||
for start in [0.13, -0.17, 0.31] {
|
for start in [0.13, -0.17, 0.31] {
|
||||||
let extent = at(start);
|
let region = at(start);
|
||||||
let before = draws.get();
|
let before = draws.get();
|
||||||
warm.rsc[root].extent = extent;
|
warm.rsc[root].region = region;
|
||||||
warm.frame();
|
warm.frame();
|
||||||
assert_eq!(draws.get(), before);
|
assert_eq!(draws.get(), before);
|
||||||
let mut cold = Harness::new((403, 211));
|
let mut cold = Harness::new((403, 211));
|
||||||
let (_, other, other_fixed, _) = plant(&mut cold, extent);
|
let (_, other, other_fixed, _) = plant(&mut cold, region);
|
||||||
for (a, b) in [(leaf.id(), other.id()), (fixed.id(), other_fixed.id())] {
|
for (a, b) in [(leaf.id(), other.id()), (fixed.id(), other_fixed.id())] {
|
||||||
assert_eq!(warm.region(&a), cold.region(&b));
|
assert_eq!(warm.region(&a), cold.region(&b));
|
||||||
assert_eq!(primitive_bounds(&warm, a), primitive_bounds(&cold, b));
|
assert_eq!(primitive_bounds(&warm, a), primitive_bounds(&cold, b));
|
||||||
@@ -1207,7 +1207,7 @@ fn padding_and_stack_boxes_follow_the_extent_without_drawing_again() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn moving_an_extent_child_preserves_the_slot_chosen_from_its_measurement() {
|
fn moving_a_childs_region_preserves_the_slot_chosen_from_its_measurement() {
|
||||||
struct Measured;
|
struct Measured;
|
||||||
impl Widget for Measured {
|
impl Widget for Measured {
|
||||||
fn draw(&mut self, painter: &mut Painter) -> Size {
|
fn draw(&mut self, painter: &mut Painter) -> Size {
|
||||||
@@ -1256,7 +1256,7 @@ fn moving_an_extent_child_preserves_the_slot_chosen_from_its_measurement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
fn changing_regions_keep_fractional_reports_and_numeric_dependencies_valid() {
|
||||||
struct Container {
|
struct Container {
|
||||||
child: StrongWidget,
|
child: StrongWidget,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
@@ -1277,7 +1277,7 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
|||||||
}
|
}
|
||||||
struct Frame {
|
struct Frame {
|
||||||
child: StrongWidget,
|
child: StrongWidget,
|
||||||
extent: UiRegion,
|
region: UiRegion,
|
||||||
answer: Rc<Cell<Size>>,
|
answer: Rc<Cell<Size>>,
|
||||||
}
|
}
|
||||||
impl Widget for Frame {
|
impl Widget for Frame {
|
||||||
@@ -1288,8 +1288,8 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
|||||||
&self.child,
|
&self.child,
|
||||||
[None; 2],
|
[None; 2],
|
||||||
[
|
[
|
||||||
Place::Fill(Part::From(self.extent.x)),
|
Place::Fill(Part::From(self.region.x)),
|
||||||
Place::Fill(Part::From(self.extent.y)),
|
Place::Fill(Part::From(self.region.y)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.size(),
|
.size(),
|
||||||
@@ -1302,7 +1302,7 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
|||||||
UiRegion::FULL,
|
UiRegion::FULL,
|
||||||
UiRegion::new(UiSpan::new(Len::rel(0.13), Len::rel(0.79)), UiSpan::FULL),
|
UiRegion::new(UiSpan::new(Len::rel(0.13), Len::rel(0.79)), UiSpan::FULL),
|
||||||
] {
|
] {
|
||||||
let plant = |h: &mut Harness, extent| {
|
let plant = |h: &mut Harness, outer| {
|
||||||
let size = if fractional {
|
let size = if fractional {
|
||||||
Size {
|
Size {
|
||||||
x: rel(0.5),
|
x: rel(0.5),
|
||||||
@@ -1320,7 +1320,7 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
|||||||
let answer = Rc::new(Cell::new(Size::ZERO));
|
let answer = Rc::new(Cell::new(Size::ZERO));
|
||||||
let root = Frame {
|
let root = Frame {
|
||||||
child,
|
child,
|
||||||
extent,
|
region: outer,
|
||||||
answer: answer.clone(),
|
answer: answer.clone(),
|
||||||
}
|
}
|
||||||
.add(&mut h.rsc);
|
.add(&mut h.rsc);
|
||||||
@@ -1330,12 +1330,12 @@ fn extent_frames_keep_fractional_reports_and_numeric_dependencies_valid() {
|
|||||||
let mut warm = Harness::new((403, 211));
|
let mut warm = Harness::new((403, 211));
|
||||||
let (root, leaf, answer) = plant(&mut warm, UiRegion::FULL);
|
let (root, leaf, answer) = plant(&mut warm, UiRegion::FULL);
|
||||||
for width in [191.125, 297.25, 83.75] {
|
for width in [191.125, 297.25, 83.75] {
|
||||||
let extent =
|
let region =
|
||||||
UiRegion::new(UiSpan::new(Len::px(13.125), Len::px(width)), UiSpan::FULL);
|
UiRegion::new(UiSpan::new(Len::px(13.125), Len::px(width)), UiSpan::FULL);
|
||||||
warm.rsc[root].extent = extent;
|
warm.rsc[root].region = region;
|
||||||
warm.frame();
|
warm.frame();
|
||||||
let mut cold = Harness::new((403, 211));
|
let mut cold = Harness::new((403, 211));
|
||||||
let (_, other, other_answer) = plant(&mut cold, extent);
|
let (_, other, other_answer) = plant(&mut cold, region);
|
||||||
assert_eq!(answer.get(), other_answer.get());
|
assert_eq!(answer.get(), other_answer.get());
|
||||||
assert_eq!(warm.region(&leaf), cold.region(&other));
|
assert_eq!(warm.region(&leaf), cold.region(&other));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -406,8 +406,8 @@ fn describe_widget(id: WidgetId, h: &Harness) -> String {
|
|||||||
fn record(id: WidgetId, h: &Harness) -> String {
|
fn record(id: WidgetId, h: &Harness) -> String {
|
||||||
let active = &h.render.active[&id];
|
let active = &h.render.active[&id];
|
||||||
format!(
|
format!(
|
||||||
"frame {} ask {} box {} size {}",
|
"frame {} region {} placement {} size {}",
|
||||||
active.frame, active.part, active.extent, active.size,
|
active.frame, active.region, active.placement, active.size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user