iris: make span compaction explicit

This commit is contained in:
iris committed 2026-09-12 21:18:09 -04:00
1 parent 54e6765a1d
commit 5f4975285d
4 files changed
+90 -19

No files matched your search

+2
View File
@@ -100,10 +100,12 @@ where
rect(PaintId::PURPLE).sized((50, 50)).align(Align::TOP),
)
.span(Dir::RIGHT)
.compact()
.center(),
wtext("pretty cool right?").size(50),
)
.span(Dir::DOWN)
.compact()
.add(rsc);
let texts = Span::empty(Dir::DOWN).gap(10).add(rsc);
+10 -18
View File
@@ -38,24 +38,17 @@ where
.add(Srgba8::new(53, 57, 66, 255).to_linear());
let styled = "Bold, italic, underlined, and colored spans";
let styled = wtext(styled)
.size(20)
.spans(vec![
SpanStyle::new(0..4).bold(),
SpanStyle::new(6..12).italic(),
SpanStyle::new(14..24).underline(),
SpanStyle::new(30..37).color(PaintId::SKY),
])
.width(rest(1));
let styled = wtext(styled).size(20).spans(vec![
SpanStyle::new(0..4).bold(),
SpanStyle::new(6..12).italic(),
SpanStyle::new(14..24).underline(),
SpanStyle::new(30..37).color(PaintId::SKY),
]);
let aligned = (
wtext("Left aligned")
.text_align(Align::CENTER_LEFT)
.width(rest(1)),
wtext("Centered").text_align(Align::CENTER).width(rest(1)),
wtext("Right aligned")
.text_align(Align::CENTER_RIGHT)
.width(rest(1)),
wtext("Left aligned").text_align(Align::CENTER_LEFT),
wtext("Centered").text_align(Align::CENTER),
wtext("Right aligned").text_align(Align::CENTER_RIGHT),
)
.span(Dir::DOWN)
.gap(dp(4))
@@ -84,8 +77,7 @@ where
.spans(vec![SpanStyle::new(0..9).bold()]),
wtext("Drag across display text to select it. The overflow markers select hidden source text, but are never copied.")
.overflow(TextOverflow::Wrap)
.color(PaintId::GRAY)
.width(rest(1)),
.color(PaintId::GRAY),
)
.span(Dir::DOWN)
.gap(dp(6))
+57
View File
@@ -204,6 +204,7 @@ fn a_span_reuses_unchanged_sibling_sizes_when_only_its_along_extent_changes() {
children: vec![changed.any(), sibling.any()],
dir: Dir::DOWN,
gap: LayoutLen::ZERO,
compact_orthogonal: false,
});
let root = rsc
.ui
@@ -231,6 +232,61 @@ fn a_span_reuses_unchanged_sibling_sizes_when_only_its_along_extent_changes() {
);
}
#[test]
fn a_span_leaves_children_in_its_offered_orthogonal_axis_by_default() {
let mut rsc = TestRsc { ui: Ui::default() };
let short = wtext("short").add(&mut rsc);
let root = (short, wtext("a much wider line"))
.span(Dir::DOWN)
.add_strong(&mut rsc);
let root_id = root.id();
let root = root.any();
let mut render = UiRenderState::new();
render.resize((200.0, 100.0));
render.update(&root, &mut rsc);
let width = render.active[&root_id].size.x;
assert_eq!(width.rel, 0.0);
assert_eq!(width.rest, 0.0);
assert!(width.abs > 0.0 && width.abs < 200.0);
assert_eq!(
render.active[&short.id()]
.region
.to_px(vec2(200.0, 100.0))
.size()
.x,
200.0,
);
}
#[test]
fn a_compact_span_shrinks_its_orthogonal_axis_to_its_widest_child() {
let mut rsc = TestRsc { ui: Ui::default() };
let short = wtext("short").add(&mut rsc);
let root = (short, wtext("a much wider line"))
.span(Dir::DOWN)
.compact()
.add_strong(&mut rsc);
let root_id = root.id();
let root = root.any();
let mut render = UiRenderState::new();
render.resize((200.0, 100.0));
render.update(&root, &mut rsc);
let width = render.active[&root_id].size.x;
assert_eq!(width.rel, 0.0);
assert_eq!(width.rest, 0.0);
assert!(width.abs > 0.0 && width.abs < 200.0);
assert_eq!(
render.active[&short.id()]
.region
.to_px(vec2(200.0, 100.0))
.size()
.x,
width.abs,
);
}
#[test]
fn a_child_coordinate_offset_moves_only_the_child_subtree() {
let mut rsc = TestRsc { ui: Ui::default() };
@@ -1077,6 +1133,7 @@ fn a_span_of_padded_children_inside_a_span_draws_each_where_its_box_is() {
children: vec![header.any(), inner.any()],
dir: Dir::DOWN,
gap: LayoutLen::ZERO,
compact_orthogonal: false,
});
let mut list = LazySpan::new(Dir::DOWN, Pin::End);
list.push_back(LazyItem::new(0, outer.any()));
+21 -1
View File
@@ -5,6 +5,7 @@ pub struct Span {
pub children: Vec<StrongWidget>,
pub dir: Dir,
pub gap: LayoutLen,
pub compact_orthogonal: bool,
}
impl Widget for Span {
@@ -85,7 +86,7 @@ impl Widget for Span {
}
if ortho_mixed {
ortho_len = LayoutLen::default();
} else {
} else if self.compact_orthogonal {
let ortho = ortho_len
.apply_rest(painter.density())
.align(AxisAlign::Neg);
@@ -111,9 +112,18 @@ impl Span {
children: Vec::new(),
dir,
gap: LayoutLen::ZERO,
compact_orthogonal: false,
}
}
/// Shrink the span and its children to the widest orthogonal child
/// instead of leaving children in the orthogonal space offered by its
/// parent.
pub fn compact(mut self) -> Self {
self.compact_orthogonal = true;
self
}
pub fn gap(mut self, gap: impl Into<LayoutLen>) -> Self {
self.gap = gap.into();
self
@@ -132,6 +142,7 @@ pub struct SpanBuilder<State, const LEN: usize, Wa: WidgetArrLike<State, LEN, Ta
pub children: Wa,
pub dir: Dir,
pub gap: LayoutLen,
pub compact_orthogonal: bool,
_pd: PhantomData<(State, Tag)>,
}
@@ -146,6 +157,7 @@ impl<Rsc, const LEN: usize, Wa: WidgetArrLike<Rsc, LEN, Tag>, Tag> WidgetFnTrait
children: self.children.add(rsc).arr.into_iter().collect(),
dir: self.dir,
gap: self.gap,
compact_orthogonal: self.compact_orthogonal,
}
}
}
@@ -158,6 +170,7 @@ impl<State, const LEN: usize, Wa: WidgetArrLike<State, LEN, Tag>, Tag>
children,
dir,
gap: LayoutLen::ZERO,
compact_orthogonal: false,
_pd: PhantomData,
}
}
@@ -166,6 +179,13 @@ impl<State, const LEN: usize, Wa: WidgetArrLike<State, LEN, Tag>, Tag>
self.gap = gap.into();
self
}
/// Shrink the span and its children to the widest orthogonal child
/// instead of filling the orthogonal space offered by its parent.
pub fn compact(mut self) -> Self {
self.compact_orthogonal = true;
self
}
}
impl std::ops::Deref for Span {