use { std::{ sync::{Arc, RwLock} }, cgmath::{Point2, Vector2}, crate::{ core::{ View, Observer, ObserverExt, ObserverBroadcast, InnerViewPort }, index::{IndexView}, grid::{GridView} } }; pub struct GridOffset { src: Option>, offset: Vector2, cast: Arc>>> } impl GridOffset where V::Item: Default { pub fn new(port: InnerViewPort>) -> Arc> { let offset_view = Arc::new(RwLock::new( GridOffset:: { src: None, offset: Vector2::new(0, 0), cast: port.get_broadcast() } )); port.set_view(Some(offset_view.clone())); offset_view } pub fn set_offset(&mut self, new_offset: Vector2) { let old_area = self.area(); self.offset = new_offset; 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); } } } impl View for GridOffset { type Msg = Point2; } impl IndexView> for GridOffset where V::Item: Default { type Item = V::Item; fn get(&self, pos: &Point2) -> Self::Item { if let Some(src) = self.src.as_ref() { src.get(&(pos - self.offset)) } else { Self::Item::default() } } fn area(&self) -> Option>> { Some( self.src.as_ref()? .area()?.into_iter() .map(|pos| pos + self.offset) .collect() ) } } impl Observer for GridOffset where V::Item: Default { fn reset(&mut self, view: Option>) { let old_area = self.area(); self.src = 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(&self, msg: &Point2) { self.cast.notify(&(msg + self.offset)); } }