From f76a56f7b9bc2075217840ca4e3b8434fdf80a0a Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Tue, 12 Jan 2021 22:33:47 +0100 Subject: [PATCH] add GridOffset --- src/grid_offset.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/grid_offset.rs diff --git a/src/grid_offset.rs b/src/grid_offset.rs new file mode 100644 index 0000000..f4ec661 --- /dev/null +++ b/src/grid_offset.rs @@ -0,0 +1,99 @@ +use { + std::{ + sync::{Arc, RwLock}, + ops::Range + }, + cgmath::{Point2, Vector2}, + crate::{ + core::{ + View, + Observer, + ObserverExt, + ObserverBroadcast, + InnerViewPort + }, + view::{ + index::{IndexView, ImplIndexView}, + grid::{GridView, GridWindowIterator} + } + } +}; + +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_range = self.range(); + self.offset = new_offset; + let new_range = self.range(); + + if let Some(old_range) = old_range { + self.cast.notify_each(GridWindowIterator::from(old_range)); + } + if let Some(new_range) = new_range { + self.cast.notify_each(GridWindowIterator::from(new_range)); + } + } +} + +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 range(&self) -> Option>> { + let src_range = self.src.as_ref()?.range()?; + Some((src_range.start + self.offset) .. (src_range.end + self.offset)) + } +} + +impl Observer for GridOffset +where V::Item: Default { + fn reset(&mut self, view: Option>) { + let old_range = self.range(); + self.src = view; + let new_range = self.range(); + + if let Some(old_range) = old_range { + self.cast.notify_each(GridWindowIterator::from(old_range)); + } + if let Some(new_range) = new_range { + self.cast.notify_each(GridWindowIterator::from(new_range)); + } + } + + fn notify(&self, msg: &Point2) { + self.cast.notify(&(msg + self.offset)); + } +} +