use crate::binding::{BindingOptions, IObservableCollection, IObservableCollectionAdaptor, ISortedObservableCollectionAdaptor, ObservableCollectionAdaptor, ObservableCollectionExtended, ReadOnlyObservableCollection, SortedObservableCollectionAdaptor};
use crate::cache::{ChangeSet, IChangeSet, ISortedChangeSet, PagedChangeSet, SortedChangeSet};
use crate::DynamicDataOptions;
use ferroui_reactive::ObservableExt;
use ferroui_system::IObservable;
use std::any::Any;
use std::hash::Hash;
use std::rc::Rc;
pub(crate) fn as_sorted_stream<S: 'static, T: 'static, K: 'static>(source: &S) -> Option<Rc<dyn IObservable<SortedChangeSet<T, K>>>>
where
T: Clone,
K: Clone,
{
let source = source as &dyn Any;
if let Some(sorted) = source.downcast_ref::<Rc<dyn IObservable<SortedChangeSet<T, K>>>>() {
return Some(sorted.clone());
}
if let Some(paged) = source.downcast_ref::<Rc<dyn IObservable<PagedChangeSet<T, K>>>>() {
return Some(paged.select(|changes: PagedChangeSet<T, K>| changes.to_sorted_change_set()));
}
if let Some(virtualised) = source.downcast_ref::<Rc<dyn IObservable<crate::cache::VirtualChangeSet<T, K>>>>() {
return Some(virtualised.select(|changes: crate::cache::VirtualChangeSet<T, K>| changes.to_sorted_change_set()));
}
None
}
pub(crate) fn expect_sorted_stream<S: 'static, T: Clone + 'static, K: Clone + 'static>(source: &S) -> Rc<dyn IObservable<SortedChangeSet<T, K>>> {
as_sorted_stream(source).expect("a sorted adaptor binds a sequence of sorted change sets (Sort, Page, Virtualise)")
}
pub(crate) fn binding_options(reset_threshold: usize, use_replace_for_updates: bool) -> BindingOptions {
let defaults = DynamicDataOptions::binding();
if reset_threshold == BindingOptions::DEFAULT_RESET_THRESHOLD && use_replace_for_updates == BindingOptions::DEFAULT_USE_REPLACE_FOR_UPDATES {
defaults
} else {
defaults.with_reset_threshold(reset_threshold).with_use_replace_for_updates(use_replace_for_updates)
}
}
pub(crate) fn bind_with_adaptor<T: Clone + PartialEq + 'static, K: 'static>(
source: Rc<dyn IObservable<ChangeSet<T, K>>>,
destination: Rc<dyn IObservableCollection<T>>,
updater: Rc<dyn IObservableCollectionAdaptor<T, K>>,
) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
source.select(move |changes: ChangeSet<T, K>| {
updater.adapt(&changes, &*destination);
changes
})
}
pub(crate) fn bind_sorted_with_adaptor<T: Clone + PartialEq + 'static, K: 'static>(
source: Rc<dyn IObservable<SortedChangeSet<T, K>>>,
destination: Rc<dyn IObservableCollection<T>>,
updater: Rc<dyn ISortedObservableCollectionAdaptor<T, K>>,
) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
source.select(move |changes: SortedChangeSet<T, K>| {
updater.adapt(&changes, &*destination);
changes.change_set().clone()
})
}
pub(crate) fn bind_with_options<S: 'static, T: Clone + PartialEq + 'static, K: Eq + Hash + Clone + 'static>(
source: &S,
plain: Rc<dyn IObservable<ChangeSet<T, K>>>,
destination: Rc<dyn IObservableCollection<T>>,
options: BindingOptions,
) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
match as_sorted_stream::<S, T, K>(source) {
Some(sorted) => bind_sorted_with_adaptor(sorted, destination, Rc::new(SortedObservableCollectionAdaptor::with_options(options))),
None => bind_with_adaptor(plain, destination, Rc::new(ObservableCollectionAdaptor::<T, K>::with_options(options))),
}
}
pub(crate) fn new_read_only_target<T: Clone + PartialEq + 'static>(capacity: Option<usize>) -> (ObservableCollectionExtended<T>, ReadOnlyObservableCollection<T>) {
let target = match capacity {
Some(capacity) if capacity > 0 => ObservableCollectionExtended::with_capacity(capacity),
_ => ObservableCollectionExtended::new(),
};
let read_only = ReadOnlyObservableCollection::from(&target);
(target, read_only)
}
pub(crate) fn bind_context_stream<S: 'static, T, K, L>(source: &S, target: L, options: Option<crate::binding::SortAndBindOptions>) -> Option<Rc<dyn IObservable<ChangeSet<T, K>>>>
where
T: Clone + PartialEq + 'static,
K: Eq + Hash + Clone + 'static,
L: crate::list::IList<T> + Clone + 'static,
{
use crate::cache::{ChangeSetWithContext, PageContext, VirtualContext};
let source = source as &dyn Any;
if let Some(paged) = source.downcast_ref::<Rc<dyn IObservable<ChangeSetWithContext<T, K, PageContext<T>>>>>() {
return Some(crate::binding::bind_paged::bind_with_context(paged.clone(), target, options));
}
if let Some(virtualised) = source.downcast_ref::<Rc<dyn IObservable<ChangeSetWithContext<T, K, VirtualContext<T>>>>>() {
return Some(crate::binding::bind_paged::bind_with_context(virtualised.clone(), target, options));
}
None
}
pub(crate) fn expect_bind_context_stream<S: 'static, T, K, L>(source: &S, target: L, options: Option<crate::binding::SortAndBindOptions>) -> Rc<dyn IObservable<ChangeSet<T, K>>>
where
T: Clone + PartialEq + 'static,
K: Eq + Hash + Clone + 'static,
L: crate::list::IList<T> + Clone + 'static,
{
bind_context_stream(source, target, options).expect("binding to a list needs the change sets of SortAndPage or SortAndVirtualize")
}