Callback can now return a result

This commit is contained in:
Jonathan Johnson 2023-10-27 12:25:31 -07:00
parent 304032f1b0
commit 5b94d37b6f
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
4 changed files with 29 additions and 35 deletions

View file

@ -31,12 +31,7 @@ impl<T> Dynamic<T> {
} }
pub fn map_mut<R>(&self, map: impl FnOnce(&mut T) -> R) -> R { pub fn map_mut<R>(&self, map: impl FnOnce(&mut T) -> R) -> R {
let mut state = self.state(); self.0.map_mut(map)
state.wrapped.generation = state.wrapped.generation.wrapping_add(1);
let result = map(&mut state.wrapped.value);
drop(state);
self.0.sync.notify_all();
result
} }
pub fn for_each<F>(&self, mut map: F) pub fn for_each<F>(&self, mut map: F)
@ -72,7 +67,7 @@ impl<T> Dynamic<T> {
#[must_use] #[must_use]
pub fn replace(&self, new_value: T) -> T { 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) { pub fn set(&self, new_value: T) {
@ -150,18 +145,13 @@ impl<T> DynamicData<T> {
} }
#[must_use] #[must_use]
pub fn replace(&self, new_value: T) -> GenerationalValue<T> { pub fn map_mut<R>(&self, map: impl FnOnce(&mut T) -> R) -> R {
let mut state = self.state(); let mut state = self.state();
let old = { let old = {
let state = &mut *state; let state = &mut *state;
let generation = state.wrapped.generation.wrapping_add(1); let generation = state.wrapped.generation.wrapping_add(1);
let old = std::mem::replace( let result = map(&mut state.wrapped.value);
&mut state.wrapped, state.wrapped.generation = generation;
GenerationalValue {
value: new_value,
generation,
},
);
for callback in &mut state.callbacks { for callback in &mut state.callbacks {
callback.update(&state.wrapped); callback.update(&state.wrapped);
@ -169,7 +159,7 @@ impl<T> DynamicData<T> {
for window in state.windows.drain(..) { for window in state.windows.drain(..) {
let _result = window.send(WindowCommand::Redraw); let _result = window.send(WindowCommand::Redraw);
} }
old result
}; };
drop(state); drop(state);

View file

@ -11,7 +11,7 @@ use kludgine::app::winit::event::{
use kludgine::figures::units::{Px, UPx}; use kludgine::figures::units::{Px, UPx};
use kludgine::figures::{Point, Rect, Size}; use kludgine::figures::{Point, Rect, Size};
use crate::context::{EventContext, GraphicsContext}; use crate::context::{EventContext, GraphicsContext, WidgetContext};
use crate::dynamic::Dynamic; use crate::dynamic::Dynamic;
use crate::styles::{Component, Group, Styles}; use crate::styles::{Component, Group, Styles};
use crate::tree::{Tree, WidgetId}; use crate::tree::{Tree, WidgetId};
@ -246,6 +246,12 @@ impl<T> Value<T> {
Value::Dynamic(value) => Some(value.generation()), 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<T> { pub trait IntoValue<T> {
@ -276,9 +282,9 @@ impl<T> IntoValue<T> for Value<T> {
} }
} }
pub struct Callback<T>(Box<dyn CallbackFunction<T>>); pub struct Callback<T = (), R = ()>(Box<dyn CallbackFunction<T, R>>);
impl<T> Debug for Callback<T> { impl<T, R> Debug for Callback<T, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Callback") f.debug_tuple("Callback")
.field(&(self as *const Self)) .field(&(self as *const Self))
@ -286,28 +292,29 @@ impl<T> Debug for Callback<T> {
} }
} }
impl<T> Callback<T> { impl<T, R> Callback<T, R> {
pub fn new<F>(function: F) -> Self pub fn new<F>(function: F) -> Self
where where
F: FnMut(T) + Send + UnwindSafe + 'static, F: FnMut(T) -> R + Send + UnwindSafe + 'static,
{ {
Self(Box::new(function)) Self(Box::new(function))
} }
pub fn invoke(&mut self, value: T) { pub fn invoke(&mut self, value: T) -> R {
self.0.invoke(value); self.0.invoke(value)
} }
} }
trait CallbackFunction<T>: Send + UnwindSafe { trait CallbackFunction<T, R>: Send + UnwindSafe {
fn invoke(&mut self, value: T); fn invoke(&mut self, value: T) -> R;
} }
impl<T, F> CallbackFunction<T> for F
impl<T, R, F> CallbackFunction<T, R> for F
where where
F: FnMut(T) + Send + UnwindSafe, F: FnMut(T) -> R + Send + UnwindSafe,
{ {
fn invoke(&mut self, value: T) { fn invoke(&mut self, value: T) -> R {
self(value); self(value)
} }
} }

View file

@ -50,9 +50,7 @@ impl Button {
impl Widget for Button { impl Widget for Button {
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
let center = Point::from(context.graphics.size()) / 2; let center = Point::from(context.graphics.size()) / 2;
if let Value::Dynamic(label) = &self.label { self.label.redraw_when_changed(context);
context.redraw_when_changed(label);
}
let styles = context.query_style(&[ let styles = context.query_style(&[
&TextColor, &TextColor,

View file

@ -22,10 +22,9 @@ impl Label {
impl Widget for Label { impl Widget for Label {
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
self.contents.redraw_when_changed(context);
let center = Point::from(context.graphics.size()) / 2; 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 styles = context.query_style(&[&TextColor]);
let width = context.graphics.size().width; let width = context.graphics.size().width;
self.contents.map(|contents| { self.contents.map(|contents| {