From 4379565e3d08babf56375d4fdf25fe2815f2ded6 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Tue, 26 Dec 2023 13:57:23 -0800 Subject: [PATCH] Label/Input caches invalidate across windows When combined with changes in Kludgine, this should round out support for sharing content between multiple windows. Closes #110 --- Cargo.lock | 2 +- examples/multi-window.rs | 18 ++++++++++++++---- src/widgets/image.rs | 8 +++++++- src/widgets/input.rs | 9 ++++++--- src/widgets/label.rs | 5 +++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8525ad8..fbb7810 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1179,7 +1179,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kludgine" version = "0.6.1" -source = "git+https://github.com/khonsulabs/kludgine#cda8f82c6e9772b26e80a7e925984c7eec0d4a8f" +source = "git+https://github.com/khonsulabs/kludgine#8b0f1daaf6d1efc9f7846a0939cdd02d070a9037" dependencies = [ "ahash", "alot", diff --git a/examples/multi-window.rs b/examples/multi-window.rs index e1b73d7..ff68f0d 100644 --- a/examples/multi-window.rs +++ b/examples/multi-window.rs @@ -1,11 +1,16 @@ +use gooey::kludgine::include_texture; use gooey::value::{Dynamic, MapEach}; use gooey::widget::MakeWidget; +use gooey::widgets::Image; use gooey::{Application, Open, PendingApp, Run}; +use kludgine::LazyTexture; fn main() -> gooey::Result { // To open multiple applications, we need a handle to the application. This // starts with the `PendingApp` type. let app = PendingApp::default(); + // Gooey ensures it's easy to share resources between windows. + let texture = include_texture!("assets/ferris-happy.png").expect("valid image"); let open_windows = Dynamic::new(0_usize); let counter = Dynamic::new(0_usize); @@ -18,7 +23,8 @@ fn main() -> gooey::Result { "There are {open} other window(s) open. {counter} total windows have been opened" ) }) - .and(open_window_button(&app, &open_windows, &counter)) + .and(Image::new(texture.clone())) + .and(open_window_button(&app, &open_windows, &counter, &texture)) .into_rows() .centered() // The other examples call run() on the widget/window. Since we're @@ -27,7 +33,7 @@ fn main() -> gooey::Result { // And now let's open our first "clone" window -- the window that clicking // the open button on any of the windows will create. - open_another_window(&app, &open_windows, &counter); + open_another_window(&app, &open_windows, &counter, &texture); // Run the application app.run() @@ -38,12 +44,14 @@ fn open_window_button( app: &impl Application, open_windows: &Dynamic, counter: &Dynamic, + texture: &LazyTexture, ) -> impl MakeWidget { let app = app.as_app(); let open_windows = open_windows.clone(); let counter = counter.clone(); + let texture = texture.clone(); "Open Another Window".into_button().on_click(move |()| { - open_another_window(&app, &open_windows, &counter); + open_another_window(&app, &open_windows, &counter, &texture); }) } @@ -52,6 +60,7 @@ fn open_another_window( app: &impl Application, open_windows: &Dynamic, counter: &Dynamic, + texture: &LazyTexture, ) { let my_number = counter.map_mut(|count| { *count += 1; @@ -60,7 +69,8 @@ fn open_another_window( let open_windows = open_windows.clone(); open_windows.map_mut(|open_windows| *open_windows += 1); format!("This is window {my_number}") - .and(open_window_button(app, &open_windows, counter)) + .and(open_window_button(app, &open_windows, counter, texture)) + .and(Image::new(texture.clone())) .into_rows() .centered() .into_window() diff --git a/src/widgets/image.rs b/src/widgets/image.rs index 422c06b..f6780a0 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -2,7 +2,7 @@ use kludgine::figures::units::UPx; use kludgine::figures::{FloatConversion, IntoSigned, Point, Rect, Size, Zero}; -use kludgine::{AnyTexture, CollectedTexture, SharedTexture, Texture, TextureRegion}; +use kludgine::{AnyTexture, CollectedTexture, LazyTexture, SharedTexture, Texture, TextureRegion}; use crate::animation::ZeroToOne; use crate::context::LayoutContext; @@ -195,6 +195,12 @@ impl IntoValue for Texture { } } +impl IntoValue for LazyTexture { + fn into_value(self) -> Value { + Value::Constant(AnyTexture::from(self)) + } +} + impl IntoValue for SharedTexture { fn into_value(self) -> Value { Value::Constant(AnyTexture::from(self)) diff --git a/src/widgets/input.rs b/src/widgets/input.rs index 805fff9..f888782 100644 --- a/src/widgets/input.rs +++ b/src/widgets/input.rs @@ -18,7 +18,7 @@ use kludgine::figures::{ }; use kludgine::shapes::{Shape, StrokeOptions}; use kludgine::text::{MeasuredText, Text, TextOrigin}; -use kludgine::{Color, DrawableExt}; +use kludgine::{CanRenderTo, Color, DrawableExt}; use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation}; use zeroize::Zeroizing; @@ -344,7 +344,7 @@ where return; }; - let (mut position, _) = self.point_from_cursor(&cache, self.selection.cursor, cache.bytes); + let (mut position, _) = self.point_from_cursor(cache, self.selection.cursor, cache.bytes); position += Point::squared( context .get(&IntrinsicPadding) @@ -570,7 +570,10 @@ where } }; match &mut self.cache { - Some(cache) if cache.key == key => {} + Some(cache) + if cache.measured.can_render_to(&context.gfx) + && cache.placeholder.can_render_to(&context.gfx) + && cache.key == key => {} _ => { let (bytes, measured, placeholder, ) = self.value.map_ref(|storage| { let mut text = storage.as_str(); diff --git a/src/widgets/label.rs b/src/widgets/label.rs index 6ce7e1b..147f07c 100644 --- a/src/widgets/label.rs +++ b/src/widgets/label.rs @@ -3,7 +3,7 @@ use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{Point, Round, Size}; use kludgine::text::{MeasuredText, Text, TextOrigin}; -use kludgine::{Color, DrawableExt}; +use kludgine::{CanRenderTo, Color, DrawableExt}; use crate::context::{GraphicsContext, LayoutContext}; use crate::styles::components::TextColor; @@ -37,7 +37,8 @@ impl Label { let check_generation = self.text.generation(); match &self.prepared_text { Some((prepared, prepared_generation, prepared_width, prepared_color)) - if *prepared_generation == check_generation + if prepared.can_render_to(&context.gfx) + && *prepared_generation == check_generation && *prepared_color == color && (*prepared_width == width || ((*prepared_width < width || prepared.size.width <= width)