From a0e6623abef008c107dc26073a16b56c51821070 Mon Sep 17 00:00:00 2001 From: Shadow Cat Date: Thu, 28 Aug 2025 18:25:59 -0400 Subject: [PATCH] sized spans! --- src/core/image.rs | 2 +- src/core/span.rs | 19 ++++++++++++++++--- src/core/text.rs | 2 +- src/layout/orientation.rs | 13 +++++++++++++ src/layout/painter.rs | 12 ++++++++++-- src/layout/widget.rs | 12 ++++++++++-- src/testing/mod.rs | 2 +- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/core/image.rs b/src/core/image.rs index 7d5950f..1e313d4 100644 --- a/src/core/image.rs +++ b/src/core/image.rs @@ -10,7 +10,7 @@ impl Widget for Image { painter.draw_texture(&self.handle); } - fn size(&mut self, _: SizeCtx) -> Vec2 { + fn size(&mut self, _: &mut SizeCtx) -> Vec2 { self.handle.size() } } diff --git a/src/core/span.rs b/src/core/span.rs index acf56c3..7298022 100644 --- a/src/core/span.rs +++ b/src/core/span.rs @@ -7,7 +7,7 @@ pub struct Span { impl Widget for Span { fn draw(&mut self, painter: &mut Painter) { - let total = self.setup(painter); + let total = self.setup(&mut painter.size_ctx()); let mut start = UIScalar::min(); for (child, length) in &self.children { let mut child_region = UiRegion::full(); @@ -44,6 +44,17 @@ impl Widget for Span { painter.draw_within(child, child_region); } } + + fn size(&mut self, ctx: &mut SizeCtx) -> Vec2 { + let total = self.setup(ctx); + let axis = self.dir.axis; + let dir_len = if total.ratio != 0.0 { + ctx.size.axis(axis) + } else { + total.fixed + total.relative * ctx.screen_size.axis(axis) + }; + Vec2::from_axis(axis, dir_len, total.max_sized) + } } #[derive(Default)] @@ -51,6 +62,7 @@ pub struct SpanLenSums { pub fixed: f32, pub ratio: f32, pub relative: f32, + pub max_sized: f32, } impl Span { @@ -61,7 +73,7 @@ impl Span { } } - fn setup(&mut self, painter: &mut Painter) -> SpanLenSums { + fn setup(&mut self, ctx: &mut SizeCtx) -> SpanLenSums { self.children .iter_mut() .fold(SpanLenSums::default(), |mut s, (id, l)| { @@ -70,8 +82,9 @@ impl Span { SpanLen::Ratio(v) => s.ratio += *v, SpanLen::Relative(v) => s.relative += *v, SpanLen::Sized(v) => { - let size = painter.size(id); + let size = ctx.size(id); let len = size.axis(self.dir.axis); + s.max_sized = s.max_sized.max(size.axis(!self.dir.axis)); *v = size; s.fixed += len; } diff --git a/src/core/text.rs b/src/core/text.rs index 8ddb022..b119376 100644 --- a/src/core/text.rs +++ b/src/core/text.rs @@ -41,7 +41,7 @@ impl Widget for Text { // reuse TextureHandle } - fn size(&mut self, ctx: SizeCtx) -> Vec2 { + fn size(&mut self, ctx: &mut SizeCtx) -> Vec2 { let (handle, offset) = ctx.text .draw(&mut self.buf, &self.content, &self.attrs, ctx.textures); diff --git a/src/layout/orientation.rs b/src/layout/orientation.rs index c012ac9..363be19 100644 --- a/src/layout/orientation.rs +++ b/src/layout/orientation.rs @@ -75,4 +75,17 @@ impl Vec2 { Axis::Y => &mut self.y, } } + + pub const fn from_axis(axis: Axis, aligned: f32, ortho: f32) -> Self { + Self { + x: match axis { + Axis::X => aligned, + Axis::Y => ortho, + }, + y: match axis { + Axis::Y => aligned, + Axis::X => ortho, + }, + } + } } diff --git a/src/layout/painter.rs b/src/layout/painter.rs index 4dafe03..8e15df8 100644 --- a/src/layout/painter.rs +++ b/src/layout/painter.rs @@ -151,11 +151,19 @@ impl<'a> Painter<'a> { } pub fn size(&mut self, id: &WidgetId) -> Vec2 { - self.widgets.get_dyn_dynamic(&id.id).size(SizeCtx { + self.widgets + .get_dyn_dynamic(&id.id) + .size(&mut self.size_ctx()) + } + + pub fn size_ctx(&mut self) -> SizeCtx { + SizeCtx { + screen_size: self.screen_size, size: self.region().in_size(self.screen_size), text: self.text, textures: self.textures, - }) + widgets: self.widgets, + } } pub(crate) fn redraw(&mut self, id: &Id) { diff --git a/src/layout/widget.rs b/src/layout/widget.rs index 17aca0a..5259483 100644 --- a/src/layout/widget.rs +++ b/src/layout/widget.rs @@ -1,18 +1,26 @@ -use crate::layout::{Painter, TextData, Textures, Ui, Vec2, WidgetId, WidgetIdFnRet}; +use crate::layout::{Painter, TextData, Textures, Ui, Vec2, WidgetId, WidgetIdFnRet, Widgets}; use std::{any::Any, marker::PhantomData}; pub trait Widget: Any { fn draw(&mut self, painter: &mut Painter); - fn size(&mut self, ctx: SizeCtx) -> Vec2 { + fn size(&mut self, ctx: &mut SizeCtx) -> Vec2 { ctx.size } } pub struct SizeCtx<'a> { + pub screen_size: Vec2, pub size: Vec2, pub text: &'a mut TextData, pub textures: &'a mut Textures, + pub(super) widgets: &'a Widgets, +} + +impl SizeCtx<'_> { + pub fn size(&mut self, id: &WidgetId) -> Vec2 { + self.widgets.get_dyn_dynamic(&id.id).size(self) + } } pub struct WidgetTag; diff --git a/src/testing/mod.rs b/src/testing/mod.rs index 9361a2f..1eb052d 100644 --- a/src/testing/mod.rs +++ b/src/testing/mod.rs @@ -96,13 +96,13 @@ impl Client { text("okkk\nokkkkkk!").size(30), text("hmm").size(30), text("a").size(30), - text("pretty cool right?").size(30), ( text("'").size(30).family(Family::Monospace), text("'").size(30).family(Family::Monospace), text(":gamer mode").size(30).family(Family::Monospace), ) .span(Dir::RIGHT, [sized(); _]), + text("pretty cool right?").size(30), ) .span(Dir::DOWN, [sized(); _]), );