further simplify projection helper usage
This commit is contained in:
parent
a2d5ea7707
commit
4485b3cf13
3 changed files with 100 additions and 62 deletions
|
@ -15,12 +15,11 @@ use {
|
||||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
|
|
||||||
pub struct LeveledTermView {
|
pub struct LeveledTermView {
|
||||||
proj_helper: Option<ProjectionHelper<Self>>,
|
|
||||||
|
|
||||||
src: Arc<RwLock<dyn TerminalView>>,
|
src: Arc<RwLock<dyn TerminalView>>,
|
||||||
level: usize,
|
level: usize,
|
||||||
|
|
||||||
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
|
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
|
||||||
|
proj_helper: ProjectionHelper<Self>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LeveledTermView {
|
impl LeveledTermView {
|
||||||
|
@ -36,25 +35,22 @@ impl LeveledTermView {
|
||||||
src_port: OuterViewPort<dyn TerminalView>,
|
src_port: OuterViewPort<dyn TerminalView>,
|
||||||
dst_port: InnerViewPort<dyn TerminalView>
|
dst_port: InnerViewPort<dyn TerminalView>
|
||||||
) -> Arc<RwLock<Self>> {
|
) -> Arc<RwLock<Self>> {
|
||||||
|
let mut proj_helper = ProjectionHelper::new();
|
||||||
|
|
||||||
let v = Arc::new(RwLock::new(
|
let v = Arc::new(RwLock::new(
|
||||||
LeveledTermView {
|
LeveledTermView {
|
||||||
proj_helper: None,
|
src: proj_helper.new_index_arg(
|
||||||
src: Arc::new(RwLock::new(Option::<Arc<dyn TerminalView>>::None)),
|
src_port,
|
||||||
|
|p: &mut Self, pos: &Point2<i16>| {
|
||||||
|
p.cast.notify(pos);
|
||||||
|
}),
|
||||||
level: 0,
|
level: 0,
|
||||||
cast: dst_port.get_broadcast()
|
cast: dst_port.get_broadcast(),
|
||||||
|
proj_helper
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut projection_helper = ProjectionHelper::new(Arc::downgrade(&v));
|
v.write().unwrap().proj_helper.set_proj(&v);
|
||||||
|
|
||||||
let (src, src_obs) = projection_helper.new_arg(
|
|
||||||
|p: Arc<RwLock<Self>>, pos: &Point2<i16>| {
|
|
||||||
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()));
|
dst_port.set_view(Some(v.clone()));
|
||||||
|
|
||||||
v
|
v
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use {
|
use {
|
||||||
std::{
|
std::{
|
||||||
sync::{Arc, RwLock, Weak},
|
|
||||||
cmp::{max},
|
cmp::{max},
|
||||||
any::Any
|
any::Any,
|
||||||
|
sync::{Arc, RwLock, Weak}
|
||||||
|
},
|
||||||
|
async_std::{
|
||||||
|
stream::StreamExt
|
||||||
},
|
},
|
||||||
async_std::stream::StreamExt,
|
|
||||||
crate::{
|
crate::{
|
||||||
core::{View, Observer, ObserverExt, channel::{channel, ChannelData, ChannelSender, ChannelReceiver}},
|
core::{View, Observer, ObserverExt, OuterViewPort, channel::{channel, ChannelData, ChannelSender, ChannelReceiver}},
|
||||||
singleton::{SingletonView},
|
singleton::{SingletonView},
|
||||||
sequence::{SequenceView},
|
sequence::{SequenceView},
|
||||||
index::{IndexView}
|
index::{IndexView}
|
||||||
|
@ -17,22 +19,59 @@ use {
|
||||||
|
|
||||||
pub struct ProjectionHelper<P: Send + Sync + 'static> {
|
pub struct ProjectionHelper<P: Send + Sync + 'static> {
|
||||||
keepalive: Vec<Arc<dyn Any + Send + Sync>>,
|
keepalive: Vec<Arc<dyn Any + Send + Sync>>,
|
||||||
proj: Weak<RwLock<P>>
|
proj: Arc<RwLock<Weak<RwLock<P>>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Send + Sync + 'static> ProjectionHelper<P> {
|
impl<P: Send + Sync + 'static> ProjectionHelper<P> {
|
||||||
pub fn new(proj: Weak<RwLock<P>>) -> Self {
|
pub fn new() -> Self {
|
||||||
ProjectionHelper {
|
ProjectionHelper {
|
||||||
keepalive: Vec::new(),
|
keepalive: Vec::new(),
|
||||||
proj
|
proj: Arc::new(RwLock::new(Weak::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_proj(&mut self, proj: &Arc<RwLock<P>>) {
|
||||||
|
*self.proj.write().unwrap() = Arc::downgrade(proj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: make this functions generic over the View
|
||||||
|
// this does currently not work because Observer<V> is not implemented for ProjectionArg for *all* V.
|
||||||
|
|
||||||
|
pub fn new_singleton_arg<Item: 'static>(
|
||||||
|
&mut self,
|
||||||
|
port: OuterViewPort<dyn SingletonView<Item = Item>>,
|
||||||
|
notify: impl Fn(&mut P, &()) + Send + Sync + 'static
|
||||||
|
) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> {
|
||||||
|
let (view, obs) = self.new_arg(notify);
|
||||||
|
port.add_observer(obs);
|
||||||
|
view
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_sequence_arg<Item: 'static>(
|
||||||
|
&mut self,
|
||||||
|
port: OuterViewPort<dyn SequenceView<Item = Item>>,
|
||||||
|
notify: impl Fn(&mut P, &usize) + Send + Sync + 'static
|
||||||
|
) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> {
|
||||||
|
let (view, obs) = self.new_arg(notify);
|
||||||
|
port.add_observer(obs);
|
||||||
|
view
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_index_arg<Key: Clone + Send + Sync + 'static, Item: 'static>(
|
||||||
|
&mut self,
|
||||||
|
port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
|
||||||
|
notify: impl Fn(&mut P, &Key) + Send + Sync + 'static
|
||||||
|
) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> {
|
||||||
|
let (view, obs) = self.new_arg(notify);
|
||||||
|
port.add_observer(obs);
|
||||||
|
view
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_arg<
|
pub fn new_arg<
|
||||||
V: View + ?Sized + 'static
|
V: View + ?Sized + 'static
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
notify: impl Fn(Arc<RwLock<P>>, &V::Msg) + Send + Sync + 'static
|
notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static
|
||||||
) -> (
|
) -> (
|
||||||
Arc<RwLock<Option<Arc<V>>>>,
|
Arc<RwLock<Option<Arc<V>>>>,
|
||||||
Arc<RwLock<ProjectionArg<V, Vec<V::Msg>>>>
|
Arc<RwLock<ProjectionArg<V, Vec<V::Msg>>>>
|
||||||
|
@ -49,8 +88,16 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
|
||||||
let proj = self.proj.clone();
|
let proj = self.proj.clone();
|
||||||
async_std::task::spawn(async move {
|
async_std::task::spawn(async move {
|
||||||
while let Some(msg) = rx.next().await {
|
while let Some(msg) = rx.next().await {
|
||||||
let proj = proj.upgrade().unwrap();
|
if let Some(proj) = proj.read().unwrap().upgrade() {
|
||||||
notify(proj, &msg);
|
loop {
|
||||||
|
if let Ok(p) = proj.try_write().as_mut() {
|
||||||
|
notify(&mut *p, &msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
async_std::task::yield_now();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -119,12 +119,12 @@ pub mod insert_view {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct StringInsertView {
|
pub struct StringInsertView {
|
||||||
proj_helper: Option<ProjectionHelper<Self>>,
|
|
||||||
|
|
||||||
cursor: Arc<dyn SingletonView<Item = usize>>,
|
cursor: Arc<dyn SingletonView<Item = usize>>,
|
||||||
data: Arc<RwLock<dyn SequenceView<Item = char>>>,
|
data: Arc<RwLock<dyn SequenceView<Item = char>>>,
|
||||||
cur_pos: usize,
|
cur_pos: usize,
|
||||||
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
|
|
||||||
|
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
|
||||||
|
proj_helper: ProjectionHelper<Self>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for StringInsertView {
|
impl View for StringInsertView {
|
||||||
|
@ -169,45 +169,40 @@ pub mod insert_view {
|
||||||
data_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
data_port: OuterViewPort<dyn SequenceView<Item = char>>,
|
||||||
out_port: InnerViewPort<dyn TerminalView>
|
out_port: InnerViewPort<dyn TerminalView>
|
||||||
) -> Arc<RwLock<Self>> {
|
) -> Arc<RwLock<Self>> {
|
||||||
|
let mut proj_helper = ProjectionHelper::new();
|
||||||
|
|
||||||
let proj = Arc::new(RwLock::new(
|
let proj = Arc::new(RwLock::new(
|
||||||
StringInsertView {
|
StringInsertView {
|
||||||
proj_helper: None,
|
cursor: proj_helper.new_singleton_arg(
|
||||||
cursor: Arc::new(Option::<Arc<dyn SingletonView<Item = usize>>>::None),
|
cursor_port,
|
||||||
data: Arc::new(RwLock::new(Option::<Arc<dyn SequenceView<Item = char>>>::None)),
|
|s: &mut Self, _msg| {
|
||||||
cur_pos: 0,
|
let old_pos = s.cur_pos;
|
||||||
cast: out_port.get_broadcast()
|
let new_pos = s.cursor.get();
|
||||||
}
|
s.cur_pos = new_pos;
|
||||||
));
|
s.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 mut projection_helper = ProjectionHelper::new(Arc::downgrade(&proj));
|
data: proj_helper.new_sequence_arg(
|
||||||
|
data_port,
|
||||||
let (cursor, cursor_obs) = projection_helper.new_arg(
|
|s: &mut Self, idx| {
|
||||||
|s: Arc<RwLock<Self>>, _msg| {
|
s.cast.notify(&Point2::new(
|
||||||
let old_pos = s.read().unwrap().cur_pos;
|
if *idx < s.cur_pos {
|
||||||
let new_pos = s.read().unwrap().cursor.get();
|
|
||||||
s.write().unwrap().cur_pos = new_pos;
|
|
||||||
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, data_obs) = projection_helper.new_arg(
|
|
||||||
|s: Arc<RwLock<Self>>, idx| {
|
|
||||||
s.read().unwrap().cast.notify(&Point2::new(
|
|
||||||
if *idx < s.read().unwrap().cur_pos {
|
|
||||||
*idx as i16
|
*idx as i16
|
||||||
} else {
|
} else {
|
||||||
*idx as i16 + 1
|
*idx as i16 + 1
|
||||||
},
|
},
|
||||||
0
|
0
|
||||||
));
|
));
|
||||||
});
|
}),
|
||||||
|
|
||||||
proj.write().unwrap().proj_helper = Some(projection_helper);
|
cur_pos: 0,
|
||||||
proj.write().unwrap().cursor = cursor;
|
cast: out_port.get_broadcast(),
|
||||||
proj.write().unwrap().data = data;
|
|
||||||
|
|
||||||
cursor_port.add_observer(cursor_obs);
|
proj_helper
|
||||||
data_port.add_observer(data_obs);
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
proj.write().unwrap().proj_helper.set_proj(&proj);
|
||||||
out_port.set_view(Some(proj.clone()));
|
out_port.set_view(Some(proj.clone()));
|
||||||
|
|
||||||
proj
|
proj
|
||||||
|
|
Loading…
Reference in a new issue