diff --git a/src/dynamic.rs b/src/dynamic.rs index 9d1f934..e042b56 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -31,12 +31,7 @@ impl Dynamic { } pub fn map_mut(&self, map: impl FnOnce(&mut T) -> R) -> R { - let mut state = self.state(); - state.wrapped.generation = state.wrapped.generation.wrapping_add(1); - let result = map(&mut state.wrapped.value); - drop(state); - self.0.sync.notify_all(); - result + self.0.map_mut(map) } pub fn for_each(&self, mut map: F) @@ -72,7 +67,7 @@ impl Dynamic { #[must_use] pub fn replace(&self, new_value: T) -> T { - self.0.replace(new_value).value + self.0.map_mut(|value| std::mem::replace(value, new_value)) } pub fn set(&self, new_value: T) { @@ -150,18 +145,13 @@ impl DynamicData { } #[must_use] - pub fn replace(&self, new_value: T) -> GenerationalValue { + pub fn map_mut(&self, map: impl FnOnce(&mut T) -> R) -> R { let mut state = self.state(); let old = { let state = &mut *state; let generation = state.wrapped.generation.wrapping_add(1); - let old = std::mem::replace( - &mut state.wrapped, - GenerationalValue { - value: new_value, - generation, - }, - ); + let result = map(&mut state.wrapped.value); + state.wrapped.generation = generation; for callback in &mut state.callbacks { callback.update(&state.wrapped); @@ -169,7 +159,7 @@ impl DynamicData { for window in state.windows.drain(..) { let _result = window.send(WindowCommand::Redraw); } - old + result }; drop(state); diff --git a/src/widget.rs b/src/widget.rs index 9305648..4a35a91 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -11,7 +11,7 @@ use kludgine::app::winit::event::{ use kludgine::figures::units::{Px, UPx}; use kludgine::figures::{Point, Rect, Size}; -use crate::context::{EventContext, GraphicsContext}; +use crate::context::{EventContext, GraphicsContext, WidgetContext}; use crate::dynamic::Dynamic; use crate::styles::{Component, Group, Styles}; use crate::tree::{Tree, WidgetId}; @@ -246,6 +246,12 @@ impl Value { Value::Dynamic(value) => Some(value.generation()), } } + + pub fn redraw_when_changed(&self, context: &WidgetContext<'_, '_>) { + if let Value::Dynamic(dynamic) = self { + context.redraw_when_changed(dynamic); + } + } } pub trait IntoValue { @@ -276,9 +282,9 @@ impl IntoValue for Value { } } -pub struct Callback(Box>); +pub struct Callback(Box>); -impl Debug for Callback { +impl Debug for Callback { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Callback") .field(&(self as *const Self)) @@ -286,28 +292,29 @@ impl Debug for Callback { } } -impl Callback { +impl Callback { pub fn new(function: F) -> Self where - F: FnMut(T) + Send + UnwindSafe + 'static, + F: FnMut(T) -> R + Send + UnwindSafe + 'static, { Self(Box::new(function)) } - pub fn invoke(&mut self, value: T) { - self.0.invoke(value); + pub fn invoke(&mut self, value: T) -> R { + self.0.invoke(value) } } -trait CallbackFunction: Send + UnwindSafe { - fn invoke(&mut self, value: T); +trait CallbackFunction: Send + UnwindSafe { + fn invoke(&mut self, value: T) -> R; } -impl CallbackFunction for F + +impl CallbackFunction for F where - F: FnMut(T) + Send + UnwindSafe, + F: FnMut(T) -> R + Send + UnwindSafe, { - fn invoke(&mut self, value: T) { - self(value); + fn invoke(&mut self, value: T) -> R { + self(value) } } diff --git a/src/widgets/button.rs b/src/widgets/button.rs index cfc88a8..051e4e4 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -50,9 +50,7 @@ impl Button { impl Widget for Button { fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { let center = Point::from(context.graphics.size()) / 2; - if let Value::Dynamic(label) = &self.label { - context.redraw_when_changed(label); - } + self.label.redraw_when_changed(context); let styles = context.query_style(&[ &TextColor, diff --git a/src/widgets/label.rs b/src/widgets/label.rs index 3d47d14..a13c492 100644 --- a/src/widgets/label.rs +++ b/src/widgets/label.rs @@ -22,10 +22,9 @@ impl Label { impl Widget for Label { fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { + self.contents.redraw_when_changed(context); + let center = Point::from(context.graphics.size()) / 2; - if let Value::Dynamic(contents) = &mut self.contents { - context.redraw_when_changed(contents); - } let styles = context.query_style(&[&TextColor]); let width = context.graphics.size().width; self.contents.map(|contents| {