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>>>>,
chunks: HashMap<Point2<i16>, Chunk<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>
@ -81,6 +81,7 @@ where Item: 'static
Flatten {
limit: Point2::new(0, 0),
top: proj_helper.new_index_arg(
Point2::new(-1, -1),
top_port,
|s: &mut Self, chunk_idx| {
s.update_chunk(*chunk_idx);
@ -101,6 +102,7 @@ where Item: 'static
fn update_chunk(&mut self, chunk_idx: Point2<i16>) {
if let Some(chunk_port) = self.top.get(&chunk_idx) {
let view = self.proj_helper.new_index_arg(
chunk_idx,
chunk_port.clone(),
move |s: &mut Self, idx| {
if let Some(chunk) = s.chunks.get(&chunk_idx) {
@ -134,8 +136,7 @@ where Item: 'static
self.update_all_offsets();
chunk_port.0.update();
} else {
// todo:
//self.proj_helper.remove_arg();
self.proj_helper.remove_arg(&chunk_idx);
let mut dirty_idx = Vec::new();
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
b: Arc<dyn SequenceView<Item = usize>>, // PosInt, Little Endian
c: VecBuffer<usize>,
_proj_helper: ProjectionHelper<Self>
_proj_helper: ProjectionHelper<usize, Self>
}
impl Add {
@ -58,8 +58,8 @@ impl Add {
let add = Arc::new(RwLock::new(
Add {
radix,
a: proj_helper.new_sequence_arg(a, |s: &mut Self, _digit_idx| s.update()),
b: proj_helper.new_sequence_arg(b, |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(1, b, |s: &mut Self, _digit_idx| s.update()),
c: VecBuffer::new(c),
_proj_helper: proj_helper
}

View file

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

View file

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

View file

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

View file

@ -3,7 +3,8 @@ use {
cmp::{max},
any::Any,
sync::{Arc, Weak},
hash::Hash
hash::Hash,
collections::HashMap
},
std::sync::RwLock,
crate::{
@ -26,16 +27,22 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ProjectionHelper<P: Send + Sync + 'static> {
keepalive: Vec<Arc<dyn Any + Send + Sync>>,
pub struct ProjectionHelper<ArgKey, P>
where ArgKey: Clone + Hash + Eq,
P: Send + Sync + 'static
{
keepalive: HashMap<ArgKey, (usize, Arc<dyn Any + Send + Sync>)>,
proj: Arc<RwLock<Weak<RwLock<P>>>>,
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 {
ProjectionHelper {
keepalive: Vec::new(),
keepalive: HashMap::new(),
proj: Arc::new(RwLock::new(Weak::new())),
update_hooks
}
@ -50,31 +57,31 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
pub fn new_singleton_arg<Item: 'static>(
&mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn SingletonView<Item = Item>>,
notify: impl Fn(&mut P, &()) + Send + Sync + 'static
) -> 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(notify, set_channel()));
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.get_view_arc()
}
pub fn new_sequence_arg<Item: 'static>(
&mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn SequenceView<Item = Item>>,
notify: impl Fn(&mut P, &usize) + Send + Sync + 'static
) -> 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(notify, set_channel()));
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.get_view_arc()
}
pub fn new_index_arg<Key: Hash + Eq + Clone + Send + Sync + std::fmt::Debug + 'static, Item: 'static>(
&mut self,
arg_key: ArgKey,
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>>>>> {
self.update_hooks.write().unwrap().push(Arc::new(port.0.clone()));
port.add_observer(self.new_arg(notify, set_channel()));
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
port.get_view_arc()
}
@ -83,6 +90,8 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
D: ChannelData<Item = V::Msg> + 'static
>(
&mut self,
arg_key: ArgKey,
src_update: Arc<dyn UpdateTask>,
notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static,
(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,
D::IntoIter: Send + Sync + 'static
{
self.remove_arg(&arg_key);
let arg = Arc::new(RwLock::new(
ProjectionArg {
src: None,
@ -98,11 +109,27 @@ impl<P: Send + Sync + 'static> ProjectionHelper<P> {
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
}
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

View file

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

View file

@ -17,7 +17,7 @@ use {
pub struct TerminalCompositor {
layers: Vec<Arc<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>) {
let idx = self.layers.len();
self.layers.push(
self.proj_helper.new_index_arg(
idx,
v,
|s: &mut Self, pos| {
s.cast.notify(pos);