mirror of
https://github.com/danbulant/cushy
synced 2026-06-21 15:42:07 +00:00
Added Watcher type
This commit is contained in:
parent
0dd18826c9
commit
6a346ea3ef
2 changed files with 49 additions and 0 deletions
|
|
@ -36,6 +36,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `MakeWidget::to_button()`
|
||||
- `MakeWidget::to_checkbox()`
|
||||
- `WidgetInstance::to_window()`
|
||||
- `Watcher` is a new type that executes callbacks when one or more sources
|
||||
changes. This can simplify some data flows such as regenerating a value when
|
||||
many one of many UI elements are changed.
|
||||
|
||||
[139]: https://github.com/khonsulabs/cushy/issues/139
|
||||
|
||||
|
|
|
|||
46
src/value.rs
46
src/value.rs
|
|
@ -3794,6 +3794,52 @@ impl InvalidationBatch<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Watches one or more [`Source`]s and invokes associated callbacks when
|
||||
/// changed.
|
||||
///
|
||||
/// This type is useful when needing to ensure logic is executed or a value is
|
||||
/// regenerated each time one of many sources are changed.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Watcher(Dynamic<usize>);
|
||||
|
||||
impl Watcher {
|
||||
/// Ensures all callbacks attached to this watcher are invoked when `other`
|
||||
/// is changed.
|
||||
pub fn watch<T>(&self, other: &impl Source<T>)
|
||||
where
|
||||
T: Send + 'static,
|
||||
{
|
||||
let counter = self.0.clone();
|
||||
self.0
|
||||
.set_source(other.for_each_subsequent_generational(move |guard| {
|
||||
// We want to drop our guard before changing the counter to
|
||||
// ensure all callbacks associated with our counter are executed
|
||||
// without this type holding any source locks.
|
||||
drop(guard);
|
||||
let mut counter = counter.lock();
|
||||
*counter = counter.wrapping_add(1);
|
||||
}));
|
||||
}
|
||||
|
||||
/// Returns a new dynamic populated by invoking `when_changed` each time any
|
||||
/// watched source is updated.
|
||||
pub fn map_changed<F, T>(&self, mut when_changed: F) -> Dynamic<T>
|
||||
where
|
||||
F: FnMut() -> T + Send + 'static,
|
||||
T: PartialEq + Send + 'static,
|
||||
{
|
||||
self.0.map_each(move |_| when_changed())
|
||||
}
|
||||
|
||||
/// Invokes `when_changed` each time any watched source is updated.
|
||||
pub fn when_changed<F>(&self, mut when_changed: F) -> CallbackHandle
|
||||
where
|
||||
F: FnMut() + Send + 'static,
|
||||
{
|
||||
self.0.for_each(move |_| when_changed())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_cycle_is_finite() {
|
||||
crate::initialize_tracing();
|
||||
|
|
|
|||
Loading…
Reference in a new issue