1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! `AutoRefresh` (`Cache/ObservableCacheEx.AutoRefresh.cs`).
macro_rules! auto_refresh_methods {
() => {
/// The changes, with a refresh of an item whenever the property of `property_accessor`
/// changes on it, so that the operators downstream evaluate it again
/// (`AutoRefresh(Expression<Func<TObject, TProperty>>)`).
///
/// The path observes its own steps, so the items need not be `INotifyPropertyChanged`
/// themselves (upstream's constraint `TObject : INotifyPropertyChanged`).
fn auto_refresh<P: crate::binding::IntoPropertyChain<T>>(&self, property_accessor: P) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::cache::ChangeSet<T, K>>>
where
P::Value: 'static,
{
self.auto_refresh_with(property_accessor, None, None, None)
}
/// [`auto_refresh`](Self::auto_refresh) that gathers the refreshes of each
/// `change_set_buffer` into one change set and throttles the changes of the property of
/// each item by `property_change_throttle`, on `scheduler`
/// (`AutoRefresh(Expression<Func<TObject, TProperty>>, TimeSpan? changeSetBuffer, TimeSpan? propertyChangeThrottle, IScheduler? scheduler)`).
fn auto_refresh_with<P: crate::binding::IntoPropertyChain<T>>(
&self,
property_accessor: P,
change_set_buffer: Option<std::time::Duration>,
property_change_throttle: Option<std::time::Duration>,
scheduler: Option<std::rc::Rc<dyn ferroui_reactive::concurrency::IScheduler>>,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::cache::ChangeSet<T, K>>>
where
P::Value: 'static,
{
let chain = crate::binding::IntoPropertyChain::into_property_chain(property_accessor);
let throttle_scheduler = scheduler.clone();
self.auto_refresh_on_observable_with_key_with(
move |item: &T, _: &K| {
let changed = crate::binding::when_property_changed_of(chain.clone(), item.clone(), false, false);
match property_change_throttle {
None => changed,
Some(throttle) => ferroui_reactive::ObservableExt::throttle_on(
&changed,
throttle,
throttle_scheduler.clone().unwrap_or_else(ferroui_reactive::concurrency::SchedulerDefaults::default_scheduler),
),
}
},
change_set_buffer,
scheduler,
)
}
/// The changes, with a refresh of an item whenever any of its properties changes
/// (`AutoRefresh()`; the overloads of upstream share the name `AutoRefresh`).
fn auto_refresh_any(&self) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::cache::ChangeSet<T, K>>>
where
T: crate::binding::NotifyPropertyChangedEx,
{
self.auto_refresh_any_with(None, None, None)
}
/// [`auto_refresh_any`](Self::auto_refresh_any) that gathers the refreshes of each
/// `change_set_buffer` into one change set and throttles the changes of the properties of
/// each item by `property_change_throttle`, on `scheduler`
/// (`AutoRefresh(TimeSpan? changeSetBuffer, TimeSpan? propertyChangeThrottle, IScheduler? scheduler)`).
fn auto_refresh_any_with(
&self,
change_set_buffer: Option<std::time::Duration>,
property_change_throttle: Option<std::time::Duration>,
scheduler: Option<std::rc::Rc<dyn ferroui_reactive::concurrency::IScheduler>>,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::cache::ChangeSet<T, K>>>
where
T: crate::binding::NotifyPropertyChangedEx,
{
let throttle_scheduler = scheduler.clone();
self.auto_refresh_on_observable_with_key_with(
move |item: &T, _: &K| {
let changed = crate::binding::NotifyPropertyChangedEx::when_any_property_changed(item, &[]);
match property_change_throttle {
None => changed,
Some(throttle) => ferroui_reactive::ObservableExt::throttle_on(
&changed,
throttle,
throttle_scheduler.clone().unwrap_or_else(ferroui_reactive::concurrency::SchedulerDefaults::default_scheduler),
),
}
},
change_set_buffer,
scheduler,
)
}
};
}
pub(crate) use auto_refresh_methods;