From a2d5ea770763d3efff9e7a280db3523193bc8e91 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Fri, 5 Feb 2021 01:18:46 +0100 Subject: [PATCH] improve ProjectionArg, ProjectionHelper --- src/leveled_term_view.rs | 33 ++++++++------ src/projection.rs | 98 ++++++++++++++++++++++++++++------------ src/string_editor.rs | 68 ++++++++++++++++------------ 3 files changed, 127 insertions(+), 72 deletions(-) diff --git a/src/leveled_term_view.rs b/src/leveled_term_view.rs index e33cba4..6cb04de 100644 --- a/src/leveled_term_view.rs +++ b/src/leveled_term_view.rs @@ -1,20 +1,25 @@ use { - std::sync::{Arc, RwLock}, + std::{ + sync::{Arc, RwLock}, + collections::HashSet + }, cgmath::Point2, crate::{ core::{ViewPort, Observer, ObserverExt, ObserverBroadcast, InnerViewPort, OuterViewPort}, index::{ImplIndexView}, terminal::{TerminalAtom, TerminalView, TerminalStyle}, - projection::ProjectionArg + projection::{ProjectionHelper, ProjectionArg} } }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub struct LeveledTermView { - src: Arc>>>, - _src_obs: Arc>>, + proj_helper: Option>, + + src: Arc>, level: usize, + cast: Arc>> } @@ -31,24 +36,24 @@ impl LeveledTermView { src_port: OuterViewPort, dst_port: InnerViewPort ) -> Arc> { - let src_obs = ProjectionArg::new( - // we simply forward all messages - |s: Arc>, msg: &Point2| { - s.read().unwrap().cast.notify(msg); - } - ); - let v = Arc::new(RwLock::new( LeveledTermView { - src: src_obs.read().unwrap().src.clone(), - _src_obs: src_obs.clone(), + proj_helper: None, + src: Arc::new(RwLock::new(Option::>::None)), level: 0, cast: dst_port.get_broadcast() } )); - src_obs.write().unwrap().proj = Arc::downgrade(&v); + let mut projection_helper = ProjectionHelper::new(Arc::downgrade(&v)); + let (src, src_obs) = projection_helper.new_arg( + |p: Arc>, pos: &Point2| { + p.read().unwrap().cast.notify(pos); + }); + + v.write().unwrap().proj_helper = Some(projection_helper); + v.write().unwrap().src = src; src_port.add_observer(src_obs); dst_port.set_view(Some(v.clone())); diff --git a/src/projection.rs b/src/projection.rs index 00b7346..2e7831a 100644 --- a/src/projection.rs +++ b/src/projection.rs @@ -1,10 +1,12 @@ use { std::{ sync::{Arc, RwLock, Weak}, - cmp::{max} + cmp::{max}, + any::Any }, + async_std::stream::StreamExt, crate::{ - core::{View, Observer, ObserverExt}, + core::{View, Observer, ObserverExt, channel::{channel, ChannelData, ChannelSender, ChannelReceiver}}, singleton::{SingletonView}, sequence::{SequenceView}, index::{IndexView} @@ -13,46 +15,84 @@ use { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -/// Special Observer which can access the state of the projection on notify -/// also handles the reset() and default behaviour of unitinitalized inputs -pub struct ProjectionArg -where V: View + ?Sized, - P: Send + Sync { - pub src: Arc>>>, - pub proj: Weak>, - notify_fn: Box>, &V::Msg) + Send + Sync> +pub struct ProjectionHelper { + keepalive: Vec>, + proj: Weak> } -impl ProjectionArg -where V: View + ?Sized, - P: Send + Sync { - pub fn new(f: impl Fn(Arc>, &V::Msg) + Send + Sync + 'static) -> Arc> { - Arc::new(RwLock::new(ProjectionArg { - src: Arc::new(RwLock::new(None)), - proj: Weak::new(), - notify_fn: Box::new(f) - })) +impl ProjectionHelper

{ + pub fn new(proj: Weak>) -> Self { + ProjectionHelper { + keepalive: Vec::new(), + proj + } } + + pub fn new_arg< + V: View + ?Sized + 'static + >( + &mut self, + notify: impl Fn(Arc>, &V::Msg) + Send + Sync + 'static + ) -> ( + Arc>>>, + Arc>>> + ) where V::Msg: Send + Sync { + let (tx, mut rx) = channel::>(); + + let view = Arc::new(RwLock::new(None)); + let arg = Arc::new(RwLock::new( + ProjectionArg { + src: view.clone(), + sender: tx + })); + + let proj = self.proj.clone(); + async_std::task::spawn(async move { + while let Some(msg) = rx.next().await { + let proj = proj.upgrade().unwrap(); + notify(proj, &msg); + } + }); + + self.keepalive.push(arg.clone()); + + (view, arg) + } +} + +/// Special Observer which can access the state of the projection on notify +/// also handles the reset() and default behaviour of unitinitalized inputs +pub struct ProjectionArg +where V: View + ?Sized, + D: ChannelData, + D::IntoIter: Send + Sync +{ + src: Arc>>>, + sender: ChannelSender } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -impl Observer> for ProjectionArg, P> -where P: Send + Sync { +impl Observer> for ProjectionArg, D> +where D: ChannelData, + D::IntoIter: Send + Sync +{ fn reset(&mut self, new_src: Option>>) { *self.src.write().unwrap() = new_src; self.notify(&()); } fn notify(&self, msg: &()) { - (self.notify_fn)(self.proj.upgrade().unwrap(), msg); + self.sender.send(*msg); } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -impl Observer> for ProjectionArg, P> -where P: Send + Sync { +impl Observer> for ProjectionArg, D> +where D: ChannelData, + D::IntoIter: Send + Sync +{ fn reset(&mut self, new_src: Option>>) { let old_len = self.src.len().unwrap_or(0); *self.src.write().unwrap() = new_src; @@ -62,14 +102,16 @@ where P: Send + Sync { } fn notify(&self, msg: &usize) { - (self.notify_fn)(self.proj.upgrade().unwrap(), msg); + self.sender.send(*msg); } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -impl Observer> for ProjectionArg, P> -where P: Send + Sync { +impl Observer> for ProjectionArg, D> +where D: ChannelData, + D::IntoIter: Send + Sync +{ fn reset(&mut self, new_src: Option>>) { let old_area = self.src.area(); *self.src.write().unwrap() = new_src; @@ -80,7 +122,7 @@ where P: Send + Sync { } fn notify(&self, msg: &Key) { - (self.notify_fn)(self.proj.upgrade().unwrap(), msg); + self.sender.send(msg.clone()); } } diff --git a/src/string_editor.rs b/src/string_editor.rs index 7458ae3..5c1b887 100644 --- a/src/string_editor.rs +++ b/src/string_editor.rs @@ -1,5 +1,7 @@ use { - std::sync::{RwLock}, + std::{ + sync::{RwLock} + }, crate::{ core::{ViewPort, OuterViewPort}, singleton::{SingletonView, SingletonBuffer}, @@ -97,22 +99,27 @@ impl StringEditor { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub mod insert_view { - use cgmath::Point2; - use std::sync::{Arc, RwLock}; - use std::cmp::{min, max}; - use crate::{ - core::{View, Observer, ObserverExt, ObserverBroadcast, OuterViewPort, InnerViewPort}, - terminal::{TerminalAtom, TerminalStyle, TerminalView}, - grid::{GridWindowIterator}, - singleton::{SingletonView}, - sequence::{SequenceView}, - index::{IndexView}, - projection::ProjectionArg, + use { + std::{ + sync::{Arc, RwLock}, + cmp::{min, max}, + any::Any, + collections::HashSet + }, + cgmath::Point2, + crate::{ + core::{View, Observer, ObserverExt, ObserverBroadcast, OuterViewPort, InnerViewPort}, + terminal::{TerminalAtom, TerminalStyle, TerminalView}, + grid::{GridWindowIterator}, + singleton::{SingletonView}, + sequence::{SequenceView}, + index::{IndexView}, + projection::{ProjectionHelper, ProjectionArg}, + } }; pub struct StringInsertView { - _cursor_obs: Arc, Self>>>, - _data_obs: Arc, Self>>>, + proj_helper: Option>, cursor: Arc>, data: Arc>>, @@ -162,7 +169,19 @@ pub mod insert_view { data_port: OuterViewPort>, out_port: InnerViewPort ) -> Arc> { - let cursor_obs = ProjectionArg::new( + let proj = Arc::new(RwLock::new( + StringInsertView { + proj_helper: None, + cursor: Arc::new(Option::>>::None), + data: Arc::new(RwLock::new(Option::>>::None)), + cur_pos: 0, + cast: out_port.get_broadcast() + } + )); + + let mut projection_helper = ProjectionHelper::new(Arc::downgrade(&proj)); + + let (cursor, cursor_obs) = projection_helper.new_arg( |s: Arc>, _msg| { let old_pos = s.read().unwrap().cur_pos; let new_pos = s.read().unwrap().cursor.get(); @@ -170,7 +189,7 @@ pub mod insert_view { s.read().unwrap().cast.notify_each(GridWindowIterator::from(Point2::new(min(old_pos, new_pos) as i16,0) ..= Point2::new(max(old_pos, new_pos) as i16, 0))) }); - let data_obs = ProjectionArg::new( + let (data, data_obs) = projection_helper.new_arg( |s: Arc>, idx| { s.read().unwrap().cast.notify(&Point2::new( if *idx < s.read().unwrap().cur_pos { @@ -182,20 +201,9 @@ pub mod insert_view { )); }); - let proj = Arc::new(RwLock::new( - StringInsertView { - _cursor_obs: cursor_obs.clone(), - _data_obs: data_obs.clone(), - - cursor: cursor_obs.read().unwrap().src.clone(), - data: data_obs.read().unwrap().src.clone(), - cur_pos: 0, - cast: out_port.get_broadcast() - } - )); - - cursor_obs.write().unwrap().proj = Arc::downgrade(&proj); - data_obs.write().unwrap().proj = Arc::downgrade(&proj); + proj.write().unwrap().proj_helper = Some(projection_helper); + proj.write().unwrap().cursor = cursor; + proj.write().unwrap().data = data; cursor_port.add_observer(cursor_obs); data_port.add_observer(data_obs);