From 6b8e5f886b088da6e1639526af179bc5c46c3b60 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Wed, 1 Nov 2023 15:43:56 -0700 Subject: [PATCH] Update scroll example + work around cosmic_text I decided scrolling a label would work better, so I loaded a source file and noticed it wasn't rendering quite right in the label. It turns out that the text wrapping was triggering despite the width in redraw being the same as the measured amount. In short: sometimes the width I measure can't be the width I set as the cosmic_text::Buffer size, because it will cause it to wrap. I've worked around it by caching the measured text for now. But it may still show up in other situations and may require a more generalized fix by seeing what else we can gleam from the glyphs being measured. --- examples/scroll.rs | 19 ++----------------- src/widgets/label.rs | 40 ++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/examples/scroll.rs b/examples/scroll.rs index 249c48f..ee2bd5a 100644 --- a/examples/scroll.rs +++ b/examples/scroll.rs @@ -1,21 +1,6 @@ -use gooey::value::Dynamic; -use gooey::widget::Widgets; -use gooey::widgets::{Button, Scroll, Stack}; +use gooey::widgets::{Label, Scroll}; use gooey::Run; fn main() -> gooey::Result { - Scroll::new(Stack::rows( - (0..30) - .map(|i| { - let count = Dynamic::new(0); - - Button::new(count.map_each(move |count| format!("Row {i}: {count}"))).on_click( - move |_| { - count.map_mut(|count| *count += 1); - }, - ) - }) - .collect::(), - )) - .run() + Scroll::new(Label::new(include_str!("../src/widgets/scroll.rs"))).run() } diff --git a/src/widgets/label.rs b/src/widgets/label.rs index 59786c1..1713757 100644 --- a/src/widgets/label.rs +++ b/src/widgets/label.rs @@ -1,6 +1,6 @@ use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{Point, Size}; -use kludgine::text::{Text, TextOrigin}; +use kludgine::text::{MeasuredText, Text, TextOrigin}; use crate::context::GraphicsContext; use crate::styles::components::TextColor; @@ -12,6 +12,7 @@ use crate::widget::Widget; pub struct Label { /// The contents of the label. pub text: Value, + prepared_text: Option>, } impl Label { @@ -19,6 +20,7 @@ impl Label { pub fn new(text: impl IntoValue) -> Self { Self { text: text.into_value(), + prepared_text: None, } } } @@ -31,16 +33,22 @@ impl Widget for Label { let center = Point::from(size) / 2; let styles = context.query_style(&[&TextColor]); - self.text.map(|contents| { - context.graphics.draw_text( - Text::new(contents, styles.get_or_default(&TextColor)) - .origin(TextOrigin::Center) - .wrap_at(size.width), - center, - None, - None, - ); - }); + if let Some(measured) = &self.prepared_text { + context + .graphics + .draw_measured_text(measured, TextOrigin::Center, center, None, None); + } else { + self.text.map(|contents| { + context.graphics.draw_text( + Text::new(contents, styles.get_or_default(&TextColor)) + .wrap_at(size.width) + .origin(TextOrigin::Center), + center, + None, + None, + ); + }); + } } fn measure( @@ -50,12 +58,12 @@ impl Widget for Label { ) -> Size { let width = available_space.width.max().try_into().unwrap_or(Px::MAX); self.text.map(|contents| { - context + let measured = context .graphics - .measure_text(Text::from(contents).wrap_at(width)) - .size - .try_cast() - .unwrap_or_default() + .measure_text(Text::from(contents).wrap_at(width)); + let size = measured.size.try_cast().unwrap_or_default(); + self.prepared_text = Some(measured); + size }) } }