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
93
94
95
//! `TransformMany` (`List/ObservableListEx.TransformMany.cs`).
//!
//! The items of each item of the source flattened into one list. A replacement (or a refresh,
//! which takes the items again) removes the items the item no longer has and adds the new ones,
//! by the equality of the items or by `equality_comparer` (`_with_comparer`). The overloads for
//! `ObservableCollection<T>` and `ReadOnlyObservableCollection<T>` children are one method,
//! `transform_many_observable_collection`, generic over the collection (`ObservableCollectionEx`,
//! which `ObservableCollectionExtended<T>` has too).
macro_rules! transform_many_methods {
() => {
/// The items that `many_selector` gives for each item, as one list
/// (`TransformMany(Func<TSource, IEnumerable<TDestination>>, IEqualityComparer<TDestination>? equalityComparer = null)`).
fn transform_many<U: Clone + PartialEq + 'static>(
&self,
many_selector: impl Fn(&T) -> Vec<U> + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
self.transform_many_with_comparer(many_selector, |a: &U, b: &U| a == b)
}
/// [`transform_many`](Self::transform_many) whose items are compared by
/// `equality_comparer` (`TransformMany(Func<TSource, IEnumerable<TDestination>>, IEqualityComparer<TDestination>)`).
fn transform_many_with_comparer<U: Clone + PartialEq + 'static>(
&self,
many_selector: impl Fn(&T) -> Vec<U> + 'static,
equality_comparer: impl Fn(&U, &U) -> bool + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
crate::list::internal::transform_many(self.change_sets(), std::rc::Rc::new(many_selector), std::rc::Rc::new(equality_comparer))
}
/// The items of the list that `many_selector` gives for each item, as one list, followed
/// as the lists change
/// (`TransformMany(Func<TSource, IObservableList<TDestination>>, IEqualityComparer<TDestination>? equalityComparer = null)`).
fn transform_many_observable_list<U: Clone + PartialEq + 'static, C: crate::list::IObservableList<U> + 'static>(
&self,
many_selector: impl Fn(&T) -> C + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
self.transform_many_observable_list_with_comparer(many_selector, |a: &U, b: &U| a == b)
}
/// [`transform_many_observable_list`](Self::transform_many_observable_list) whose items are
/// compared by `equality_comparer`
/// (`TransformMany(Func<TSource, IObservableList<TDestination>>, IEqualityComparer<TDestination>)`).
fn transform_many_observable_list_with_comparer<U: Clone + PartialEq + 'static, C: crate::list::IObservableList<U> + 'static>(
&self,
many_selector: impl Fn(&T) -> C + 'static,
equality_comparer: impl Fn(&U, &U) -> bool + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
let many_selector: std::rc::Rc<dyn Fn(&T) -> C> = std::rc::Rc::new(many_selector);
let items_selector = many_selector.clone();
// `ManySelectorFunc`: the items of the list when they are read.
let items: std::rc::Rc<dyn Fn(&T) -> Vec<U>> = std::rc::Rc::new(move |item: &T| crate::list::IObservableList::items(&items_selector(item)));
crate::list::internal::transform_many_with_child_changes(
self.change_sets(),
items,
std::rc::Rc::new(equality_comparer),
crate::list::internal::observable_list_child_changes(many_selector),
)
}
/// The items of the observable collection that `many_selector` gives for each item, as one
/// list, followed as the collections change
/// (`TransformMany(Func<TSource, ObservableCollection<TDestination>>, IEqualityComparer<TDestination>? equalityComparer = null)`,
/// `TransformMany(Func<TSource, ReadOnlyObservableCollection<TDestination>>, IEqualityComparer<TDestination>? equalityComparer = null)`).
fn transform_many_observable_collection<U: Clone + PartialEq + 'static, C: crate::binding::ObservableCollectionEx<U> + 'static>(
&self,
many_selector: impl Fn(&T) -> C + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
self.transform_many_observable_collection_with_comparer(many_selector, |a: &U, b: &U| a == b)
}
/// [`transform_many_observable_collection`](Self::transform_many_observable_collection)
/// whose items are compared by `equality_comparer`
/// (`TransformMany(Func<TSource, ObservableCollection<TDestination>>, IEqualityComparer<TDestination>)`,
/// `TransformMany(Func<TSource, ReadOnlyObservableCollection<TDestination>>, IEqualityComparer<TDestination>)`).
fn transform_many_observable_collection_with_comparer<U: Clone + PartialEq + 'static, C: crate::binding::ObservableCollectionEx<U> + 'static>(
&self,
many_selector: impl Fn(&T) -> C + 'static,
equality_comparer: impl Fn(&U, &U) -> bool + 'static,
) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<U>>> {
let many_selector: std::rc::Rc<dyn Fn(&T) -> C> = std::rc::Rc::new(many_selector);
let items_selector = many_selector.clone();
// The collection is the enumerable of its items, read when they are needed.
let items: std::rc::Rc<dyn Fn(&T) -> Vec<U>> =
std::rc::Rc::new(move |item: &T| crate::binding::ObservableCollectionEx::notifying_collection(&items_selector(item)).to_vec());
crate::list::internal::transform_many_with_child_changes(
self.change_sets(),
items,
std::rc::Rc::new(equality_comparer),
crate::list::internal::observable_collection_child_changes(many_selector),
)
}
};
}
pub(crate) use transform_many_methods;