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 {
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<F>(&self, mut map: F)
@ -72,7 +67,7 @@ impl<T> Dynamic<T> {
#[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<T> DynamicData<T> {
}
#[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 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<T> DynamicData<T> {
for window in state.windows.drain(..) {
let _result = window.send(WindowCommand::Redraw);
}
old
result
};
drop(state);

View file

@ -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<T> Value<T> {
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> {
@ -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 {
f.debug_tuple("Callback")
.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
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<T>: Send + UnwindSafe {
fn invoke(&mut self, value: T);
trait CallbackFunction<T, R>: Send + UnwindSafe {
fn invoke(&mut self, value: T) -> R;
}
impl<T, F> CallbackFunction<T> for F
impl<T, R, F> CallbackFunction<T, R> 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)
}
}

View file

@ -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,

View file

@ -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| {