Skip to content

Instantly share code, notes, and snippets.

@arifd
Last active May 19, 2021 12:17
Show Gist options
  • Save arifd/0e10fd62d437342647be48666ca52b80 to your computer and use it in GitHub Desktop.
Save arifd/0e10fd62d437342647be48666ca52b80 to your computer and use it in GitHub Desktop.
A helper mod for the Rust Driuid GUI library, to bypass the AppDelgate in order to mutate data on a data change event
use druid::{widget::Controller, Data, Env, Event, EventCtx, Selector, UpdateCtx, Widget};
/// Bypass the `AppDelegate` entirely by appending the return from this function as a
/// `Controller` wrapping whatever you wish to perform a desired action when there is a change in the data
///
/// # Example
///
/// ```
///TextBox::new()
/// .lens(AppData::foo)
/// .controller(on_change_controller(|x| {
/// dbg!(x);
/// }))
///```
pub fn on_change_controller<T: Data + PartialEq, F: FnMut(&mut T) + 'static>(
f: F,
) -> OnChangeController<F> {
OnChangeController(f)
}
const FIELD_CHANGED: Selector = Selector::new(concat!(
file!(),
"-",
line!(),
"-",
column!(),
"-",
"field_changed"
));
pub struct OnChangeController<F>(F);
impl<T: Data + PartialEq, W: Widget<T>, F: FnMut(&mut T)> Controller<T, W>
for OnChangeController<F>
{
fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
if let Event::Command(command) = event {
if command.is(FIELD_CHANGED) {
(self.0)(data);
return;
}
}
child.event(ctx, event, data, env);
}
fn update(
&mut self,
child: &mut W,
ctx: &mut UpdateCtx<'_, '_>,
old_data: &T,
data: &T,
env: &Env,
) {
if old_data != data {
ctx.submit_command(FIELD_CHANGED.to(ctx.widget_id()));
}
child.update(ctx, old_data, data, env);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment