pub use { std::{ sync::Arc, boxed::Box }, std::sync::RwLock, crate::{ core::{ View, Observer, ObserverExt, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort }, index::{IndexView} } }; impl OuterViewPort> where SrcKey: Clone + Send + Sync + 'static, Item: 'static { pub fn map_key< DstKey: Clone + Send + Sync + 'static, F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static, F2: Fn(&DstKey) -> Option + Send + Sync + 'static, >( &self, f1: F1, f2: F2 ) -> OuterViewPort> { let port = ViewPort::new(); port.add_update_hook(Arc::new(self.0.clone())); let map = MapIndexKey::new(port.inner(), f1, f2); self.add_observer(map.clone()); port.into_outer() } } pub struct MapIndexKey where DstKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync, SrcView: IndexView + ?Sized, F1: Fn(&SrcKey) -> DstKey + Send + Sync, F2: Fn(&DstKey) -> Option + Send + Sync, { src_view: Option>, f1: F1, f2: F2, cast: Arc>>> } impl MapIndexKey where DstKey: Clone + Send + Sync + 'static, SrcKey: Clone + Send + Sync + 'static, SrcView: IndexView + ?Sized + 'static, SrcView::Item: 'static, F1: Fn(&SrcKey) -> DstKey + Send + Sync + 'static, F2: Fn(&DstKey) -> Option + Send + Sync + 'static, { fn new( port: InnerViewPort>, f1: F1, f2: F2 ) -> Arc> { let map = Arc::new(RwLock::new( MapIndexKey { src_view: None, f1, f2, cast: port.get_broadcast() } )); port.set_view(Some(map.clone())); map } } impl View for MapIndexKey where DstKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync, SrcView: IndexView + ?Sized, F1: Fn(&SrcKey) -> DstKey + Send + Sync, F2: Fn(&DstKey) -> Option + Send + Sync, { type Msg = DstKey; } impl IndexView for MapIndexKey where DstKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync, SrcView: IndexView + ?Sized, F1: Fn(&SrcKey) -> DstKey + Send + Sync, F2: Fn(&DstKey) -> Option + Send + Sync, { type Item = SrcView::Item; fn get(&self, key: &DstKey) -> Option { self.src_view.get(&(self.f2)(key)?) } fn area(&self) -> Option> { Some(self.src_view.area()?.iter().map(&self.f1).collect()) } } impl Observer for MapIndexKey where DstKey: Clone + Send + Sync, SrcKey: Clone + Send + Sync, SrcView: IndexView + ?Sized, F1: Fn(&SrcKey) -> DstKey + Send + Sync, F2: Fn(&DstKey) -> Option + Send + Sync, { fn reset(&mut self, view: Option>) { let old_area = self.area(); self.src_view = view; let new_area = self.area(); if let Some(area) = old_area { self.cast.notify_each(area); } if let Some(area) = new_area { self.cast.notify_each(area); } } fn notify(&mut self, msg: &SrcKey) { self.cast.notify(&(self.f1)(msg)); } }