projection: remove_arg

This commit is contained in:
Michael Sippel 2021-08-24 23:15:18 +02:00
parent 2563e06000
commit 5eefcbb4d1
Signed by: senvas
GPG key ID: F96CF119C34B64A6
8 changed files with 63 additions and 28 deletions

View file

@ -42,7 +42,7 @@ where Item: 'static
top: Arc<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>, top: Arc<dyn GridView<Item = OuterViewPort<dyn GridView<Item = Item>>>>,
chunks: HashMap<Point2<i16>, Chunk<Item>>, chunks: HashMap<Point2<i16>, Chunk<Item>>,
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = Item>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = Item>>>>,
proj_helper: ProjectionHelper<Self> proj_helper: ProjectionHelper<Point2<i16>, Self>
} }
impl<Item> View for Flatten<Item> impl<Item> View for Flatten<Item>
@ -81,6 +81,7 @@ where Item: 'static
Flatten { Flatten {
limit: Point2::new(0, 0), limit: Point2::new(0, 0),
top: proj_helper.new_index_arg( top: proj_helper.new_index_arg(
Point2::new(-1, -1),
top_port, top_port,
|s: &mut Self, chunk_idx| { |s: &mut Self, chunk_idx| {
s.update_chunk(*chunk_idx); s.update_chunk(*chunk_idx);
@ -101,6 +102,7 @@ where Item: 'static
fn update_chunk(&mut self, chunk_idx: Point2<i16>) { fn update_chunk(&mut self, chunk_idx: Point2<i16>) {
if let Some(chunk_port) = self.top.get(&chunk_idx) { if let Some(chunk_port) = self.top.get(&chunk_idx) {
let view = self.proj_helper.new_index_arg( let view = self.proj_helper.new_index_arg(
chunk_idx,
chunk_port.clone(), chunk_port.clone(),
move |s: &mut Self, idx| { move |s: &mut Self, idx| {
if let Some(chunk) = s.chunks.get(&chunk_idx) { if let Some(chunk) = s.chunks.get(&chunk_idx) {
@ -134,8 +136,7 @@ where Item: 'static
self.update_all_offsets(); self.update_all_offsets();
chunk_port.0.update(); chunk_port.0.update();
} else { } else {
// todo: self.proj_helper.remove_arg(&chunk_idx);
//self.proj_helper.remove_arg();
let mut dirty_idx = Vec::new(); let mut dirty_idx = Vec::new();
if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) {

View file

@ -44,7 +44,7 @@ pub struct Add {
a: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian a: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
c: VecBuffer<usize>, c: VecBuffer<usize>,
_proj_helper: ProjectionHelper<Self> _proj_helper: ProjectionHelper<usize, Self>
} }
impl Add { impl Add {
@ -58,8 +58,8 @@ impl Add {
let add = Arc::new(RwLock::new( let add = Arc::new(RwLock::new(
Add { Add {
radix, radix,
a: proj_helper.new_sequence_arg(a, |s: &mut Self, _digit_idx| s.update()), a: proj_helper.new_sequence_arg(0, a, |s: &mut Self, _digit_idx| s.update()),
b: proj_helper.new_sequence_arg(b, |s: &mut Self, _digit_idx| s.update()), b: proj_helper.new_sequence_arg(1, b, |s: &mut Self, _digit_idx| s.update()),
c: VecBuffer::new(c), c: VecBuffer::new(c),
_proj_helper: proj_helper _proj_helper: proj_helper
} }

View file

@ -19,7 +19,7 @@ pub struct LeveledTermView {
level: usize, level: usize,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<Self> proj_helper: ProjectionHelper<(), Self>
} }
impl LeveledTermView { impl LeveledTermView {
@ -40,6 +40,7 @@ impl LeveledTermView {
let v = Arc::new(RwLock::new( let v = Arc::new(RwLock::new(
LeveledTermView { LeveledTermView {
src: proj_helper.new_index_arg( src: proj_helper.new_index_arg(
(),
src_port, src_port,
|p: &mut Self, pos: &Point2<i16>| { |p: &mut Self, pos: &Point2<i16>| {
p.cast.notify(pos); p.cast.notify(pos);

View file

@ -562,7 +562,7 @@ struct ListEditorView {
cur_cursor: Option<ListCursor>, cur_cursor: Option<ListCursor>,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
proj_helper: ProjectionHelper<Self> proj_helper: ProjectionHelper<usize, Self>
} }
impl View for ListEditorView { impl View for ListEditorView {
@ -629,6 +629,7 @@ impl ListEditorView {
ListEditorView { ListEditorView {
cur_cursor: None, cur_cursor: None,
cursor: proj_helper.new_singleton_arg( cursor: proj_helper.new_singleton_arg(
0,
cursor_port, cursor_port,
|s: &mut Self, _msg| { |s: &mut Self, _msg| {
let old_cursor = s.cur_cursor; let old_cursor = s.cur_cursor;
@ -678,6 +679,7 @@ impl ListEditorView {
); );
}), }),
data: proj_helper.new_sequence_arg( data: proj_helper.new_sequence_arg(
1,
data_port, data_port,
|s: &mut Self, idx| { |s: &mut Self, idx| {
if let Some(cur) = s.cur_cursor { if let Some(cur) = s.cur_cursor {

View file

@ -22,7 +22,7 @@ pub struct ListDecorator {
item_style: TerminalStyle, item_style: TerminalStyle,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>>>,
proj_helper: ProjectionHelper<Self>, proj_helper: ProjectionHelper<(), Self>,
} }
impl View for ListDecorator { impl View for ListDecorator {
@ -77,7 +77,7 @@ impl ListDecorator {
opening_port: make_label(opening), opening_port: make_label(opening),
closing_port: make_label(closing), closing_port: make_label(closing),
delim_port: make_label(delim), delim_port: make_label(delim),
items: proj_helper.new_sequence_arg(items_port, |s: &mut Self, item_idx| { items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| {
s.cast.notify(&(*item_idx * 2 + 1)); s.cast.notify(&(*item_idx * 2 + 1));
s.cast.notify(&(*item_idx * 2 + 2)); s.cast.notify(&(*item_idx * 2 + 2));
}), }),
@ -137,7 +137,7 @@ pub struct VerticalSexprDecorator {
item_style: TerminalStyle, item_style: TerminalStyle,
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>>>,
proj_helper: ProjectionHelper<Self>, proj_helper: ProjectionHelper<(), Self>,
} }
impl View for VerticalSexprDecorator { impl View for VerticalSexprDecorator {
@ -214,7 +214,7 @@ impl VerticalSexprDecorator {
let li = Arc::new(RwLock::new(VerticalSexprDecorator { let li = Arc::new(RwLock::new(VerticalSexprDecorator {
opening_port: make_label(opening), opening_port: make_label(opening),
closing_port: make_label(closing), closing_port: make_label(closing),
items: proj_helper.new_sequence_arg(items_port, |s: &mut Self, item_idx| { items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| {
s.cast.notify(&Point2::new(1, *item_idx as i16)); s.cast.notify(&Point2::new(1, *item_idx as i16));
s.cast.notify(&Point2::new(2, *item_idx as i16 - 1)); s.cast.notify(&Point2::new(2, *item_idx as i16 - 1));
s.cast.notify(&Point2::new(2, *item_idx as i16)); s.cast.notify(&Point2::new(2, *item_idx as i16));

View file

@ -3,7 +3,8 @@ use {
cmp::{max}, cmp::{max},
any::Any, any::Any,
sync::{Arc, Weak}, sync::{Arc, Weak},
hash::Hash hash::Hash,
collections::HashMap
}, },
std::sync::RwLock, std::sync::RwLock,
crate::{ crate::{
@ -26,16 +27,22 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ProjectionHelper<P: Send + Sync + 'static> { pub struct ProjectionHelper<ArgKey, P>
keepalive: Vec<Arc<dyn Any + Send + Sync>>, where ArgKey: Clone + Hash + Eq,
P: Send + Sync + 'static
{
keepalive: HashMap<ArgKey, (usize, Arc<dyn Any + Send + Sync>)>,
proj: Arc<RwLock<Weak<RwLock<P>>>>, proj: Arc<RwLock<Weak<RwLock<P>>>>,
update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>> update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>
} }
impl<P: Send + Sync + 'static> ProjectionHelper<P> { impl<ArgKey, P> ProjectionHelper<ArgKey, P>
where ArgKey: Clone + Hash + Eq,
P: Send + Sync + 'static
{
pub fn new(update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>) -> Self { pub fn new(update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>) -> Self {
ProjectionHelper { ProjectionHelper {
keepalive: Vec::new(), keepalive: HashMap::new(),
proj: Arc::new(RwLock::new(Weak::new())), proj: Arc::new(RwLock::new(Weak::new())),
update_hooks update_hooks
} }
@ -50,31 +57,31 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
pub fn new_singleton_arg<Item: 'static>( pub fn new_singleton_arg<Item: 'static>(
&mut self, &mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn SingletonView<Item = Item>>, port: OuterViewPort<dyn SingletonView<Item = Item>>,
notify: impl Fn(&mut P, &()) + Send + Sync + 'static notify: impl Fn(&mut P, &()) + Send + Sync + 'static
) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> {
self.update_hooks.write().unwrap().push(Arc::new(port.0.clone())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.add_observer(self.new_arg(notify, set_channel()));
port.get_view_arc() port.get_view_arc()
} }
pub fn new_sequence_arg<Item: 'static>( pub fn new_sequence_arg<Item: 'static>(
&mut self, &mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn SequenceView<Item = Item>>, port: OuterViewPort<dyn SequenceView<Item = Item>>,
notify: impl Fn(&mut P, &usize) + Send + Sync + 'static notify: impl Fn(&mut P, &usize) + Send + Sync + 'static
) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> {
self.update_hooks.write().unwrap().push(Arc::new(port.0.clone())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.add_observer(self.new_arg(notify, set_channel()));
port.get_view_arc() port.get_view_arc()
} }
pub fn new_index_arg<Key: Hash + Eq + Clone + Send + Sync + std::fmt::Debug + 'static, Item: 'static>( pub fn new_index_arg<Key: Hash + Eq + Clone + Send + Sync + std::fmt::Debug + 'static, Item: 'static>(
&mut self, &mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn IndexView<Key, Item = Item>>, port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
notify: impl Fn(&mut P, &Key) + Send + Sync + 'static notify: impl Fn(&mut P, &Key) + Send + Sync + 'static
) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> { ) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> {
self.update_hooks.write().unwrap().push(Arc::new(port.0.clone())); port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.add_observer(self.new_arg(notify, set_channel()));
port.get_view_arc() port.get_view_arc()
} }
@ -83,6 +90,8 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
D: ChannelData<Item = V::Msg> + 'static D: ChannelData<Item = V::Msg> + 'static
>( >(
&mut self, &mut self,
arg_key: ArgKey,
src_update: Arc<dyn UpdateTask>,
notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static, notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static,
(tx, rx): (ChannelSender<D>, ChannelReceiver<D>) (tx, rx): (ChannelSender<D>, ChannelReceiver<D>)
) )
@ -90,6 +99,8 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
where V::Msg: Send + Sync + std::fmt::Debug, where V::Msg: Send + Sync + std::fmt::Debug,
D::IntoIter: Send + Sync + 'static D::IntoIter: Send + Sync + 'static
{ {
self.remove_arg(&arg_key);
let arg = Arc::new(RwLock::new( let arg = Arc::new(RwLock::new(
ProjectionArg { ProjectionArg {
src: None, src: None,
@ -98,11 +109,27 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
rx, tx rx, tx
})); }));
self.keepalive.push(arg.clone()); let mut hooks = self.update_hooks.write().unwrap();
let idx = hooks.len();
hooks.push(src_update);
hooks.push(arg.clone());
self.keepalive.insert(arg_key, (idx, arg.clone()));
self.update_hooks.write().unwrap().push(arg.clone());
arg arg
} }
pub fn remove_arg(&mut self, arg_key: &ArgKey) {
let mut hooks = self.update_hooks.write().unwrap();
if let Some((idx, arg)) = self.keepalive.remove(arg_key) {
hooks.remove(idx);
hooks.remove(idx);
for (_, (j, _)) in self.keepalive.iter_mut() {
if *j > idx {
*j -= 2;
}
}
}
}
} }
/// Special Observer which can access the state of the projection on notify /// Special Observer which can access the state of the projection on notify

View file

@ -39,7 +39,7 @@ where Item: 'static
top: Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>, top: Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = Item>>>>,
chunks: BTreeMap<usize, Chunk<Item>>, chunks: BTreeMap<usize, Chunk<Item>>,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = Item>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = Item>>>>,
proj_helper: ProjectionHelper<Self> proj_helper: ProjectionHelper<usize, Self>
} }
impl<Item> View for Flatten<Item> impl<Item> View for Flatten<Item>
@ -77,6 +77,7 @@ where Item: 'static
Flatten { Flatten {
length: 0, length: 0,
top: proj_helper.new_sequence_arg( top: proj_helper.new_sequence_arg(
usize::MAX,
top_port, top_port,
|s: &mut Self, chunk_idx| { |s: &mut Self, chunk_idx| {
s.update_chunk(*chunk_idx); s.update_chunk(*chunk_idx);
@ -102,6 +103,7 @@ where Item: 'static
offset: 0, // will be adjusted by update_offsets() later offset: 0, // will be adjusted by update_offsets() later
len: 0, len: 0,
view: self.proj_helper.new_sequence_arg( view: self.proj_helper.new_sequence_arg(
chunk_idx,
chunk_port.clone(), chunk_port.clone(),
move |s: &mut Self, idx| { move |s: &mut Self, idx| {
if let Some(chunk) = s.chunks.get(&chunk_idx) { if let Some(chunk) = s.chunks.get(&chunk_idx) {
@ -127,7 +129,7 @@ where Item: 'static
self.cast.notify_each(dirty_idx); self.cast.notify_each(dirty_idx);
} else { } else {
// todo: // todo:
//self.proj_helper.remove_arg(); self.proj_helper.remove_arg(&chunk_idx);
self.chunks.remove(&chunk_idx); self.chunks.remove(&chunk_idx);

View file

@ -17,7 +17,7 @@ use {
pub struct TerminalCompositor { pub struct TerminalCompositor {
layers: Vec<Arc<dyn TerminalView>>, layers: Vec<Arc<dyn TerminalView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>, cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<Self> proj_helper: ProjectionHelper<usize, Self>
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -41,8 +41,10 @@ impl TerminalCompositor {
} }
pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) { pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
let idx = self.layers.len();
self.layers.push( self.layers.push(
self.proj_helper.new_index_arg( self.proj_helper.new_index_arg(
idx,
v, v,
|s: &mut Self, pos| { |s: &mut Self, pos| {
s.cast.notify(pos); s.cast.notify(pos);