2021-01-22 14:56:56 +01:00
|
|
|
use {
|
|
|
|
std::{
|
2021-02-05 01:18:46 +01:00
|
|
|
cmp::{max},
|
2021-02-17 18:18:12 +01:00
|
|
|
any::Any,
|
2021-05-28 00:45:30 +02:00
|
|
|
sync::{Arc, Weak},
|
2021-08-24 23:15:18 +02:00
|
|
|
hash::Hash,
|
|
|
|
collections::HashMap
|
2021-01-22 14:56:56 +01:00
|
|
|
},
|
2021-03-30 22:47:05 +02:00
|
|
|
std::sync::RwLock,
|
2021-01-22 14:56:56 +01:00
|
|
|
crate::{
|
2021-05-13 16:22:30 +02:00
|
|
|
core::{
|
|
|
|
View,
|
|
|
|
Observer, ObserverExt,
|
2021-05-22 01:33:58 +02:00
|
|
|
port::UpdateTask,
|
2021-05-13 16:22:30 +02:00
|
|
|
OuterViewPort,
|
|
|
|
channel::{
|
2021-05-22 01:33:58 +02:00
|
|
|
ChannelSender, ChannelReceiver,
|
2021-05-13 16:22:30 +02:00
|
|
|
ChannelData,
|
2021-11-07 07:16:33 +01:00
|
|
|
set_channel,
|
|
|
|
queue_channel
|
2021-05-13 16:22:30 +02:00
|
|
|
}
|
|
|
|
},
|
2021-01-22 14:56:56 +01:00
|
|
|
singleton::{SingletonView},
|
|
|
|
sequence::{SequenceView},
|
2021-11-07 07:16:33 +01:00
|
|
|
index::{IndexArea, IndexView}
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
|
|
|
2021-08-24 23:15:18 +02:00
|
|
|
pub struct ProjectionHelper<ArgKey, P>
|
|
|
|
where ArgKey: Clone + Hash + Eq,
|
|
|
|
P: Send + Sync + 'static
|
|
|
|
{
|
|
|
|
keepalive: HashMap<ArgKey, (usize, Arc<dyn Any + Send + Sync>)>,
|
2021-05-22 01:33:58 +02:00
|
|
|
proj: Arc<RwLock<Weak<RwLock<P>>>>,
|
|
|
|
update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
2021-08-24 23:15:18 +02:00
|
|
|
impl<ArgKey, P> ProjectionHelper<ArgKey, P>
|
|
|
|
where ArgKey: Clone + Hash + Eq,
|
|
|
|
P: Send + Sync + 'static
|
|
|
|
{
|
2021-05-22 01:33:58 +02:00
|
|
|
pub fn new(update_hooks: Arc<RwLock<Vec<Arc<dyn UpdateTask>>>>) -> Self {
|
2021-02-05 01:18:46 +01:00
|
|
|
ProjectionHelper {
|
2021-08-24 23:15:18 +02:00
|
|
|
keepalive: HashMap::new(),
|
2021-05-22 01:33:58 +02:00
|
|
|
proj: Arc::new(RwLock::new(Weak::new())),
|
|
|
|
update_hooks
|
2021-02-05 01:18:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-17 18:18:12 +01:00
|
|
|
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,
|
2021-08-24 23:15:18 +02:00
|
|
|
arg_key: ArgKey,
|
2021-02-17 18:18:12 +01:00
|
|
|
port: OuterViewPort<dyn SingletonView<Item = Item>>,
|
|
|
|
notify: impl Fn(&mut P, &()) + Send + Sync + 'static
|
|
|
|
) -> Arc<RwLock<Option<Arc<dyn SingletonView<Item = Item>>>>> {
|
2021-08-24 23:15:18 +02:00
|
|
|
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
|
2021-05-13 23:46:22 +02:00
|
|
|
port.get_view_arc()
|
2021-02-17 18:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_sequence_arg<Item: 'static>(
|
|
|
|
&mut self,
|
2021-08-24 23:15:18 +02:00
|
|
|
arg_key: ArgKey,
|
2021-02-17 18:18:12 +01:00
|
|
|
port: OuterViewPort<dyn SequenceView<Item = Item>>,
|
|
|
|
notify: impl Fn(&mut P, &usize) + Send + Sync + 'static
|
|
|
|
) -> Arc<RwLock<Option<Arc<dyn SequenceView<Item = Item>>>>> {
|
2021-08-24 23:15:18 +02:00
|
|
|
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel()));
|
2021-05-13 23:46:22 +02:00
|
|
|
port.get_view_arc()
|
2021-02-17 18:18:12 +01:00
|
|
|
}
|
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
pub fn new_index_arg<Key: Clone + Send + Sync + 'static, Item: 'static>(
|
2021-02-17 18:18:12 +01:00
|
|
|
&mut self,
|
2021-08-24 23:15:18 +02:00
|
|
|
arg_key: ArgKey,
|
2021-02-17 18:18:12 +01:00
|
|
|
port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
|
2021-11-07 07:16:33 +01:00
|
|
|
notify: impl Fn(&mut P, &IndexArea<Key>) + Send + Sync + 'static
|
2021-02-17 18:18:12 +01:00
|
|
|
) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> {
|
2021-11-07 07:16:33 +01:00
|
|
|
port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, queue_channel()));
|
2021-05-13 23:46:22 +02:00
|
|
|
port.get_view_arc()
|
2021-02-17 18:18:12 +01:00
|
|
|
}
|
|
|
|
|
2021-02-05 01:18:46 +01:00
|
|
|
pub fn new_arg<
|
2021-05-28 00:45:30 +02:00
|
|
|
V: View + ?Sized + 'static,
|
|
|
|
D: ChannelData<Item = V::Msg> + 'static
|
2021-02-05 01:18:46 +01:00
|
|
|
>(
|
|
|
|
&mut self,
|
2021-08-24 23:15:18 +02:00
|
|
|
arg_key: ArgKey,
|
|
|
|
src_update: Arc<dyn UpdateTask>,
|
2021-05-28 00:45:30 +02:00
|
|
|
notify: impl Fn(&mut P, &V::Msg) + Send + Sync + 'static,
|
|
|
|
(tx, rx): (ChannelSender<D>, ChannelReceiver<D>)
|
|
|
|
)
|
|
|
|
-> Arc<RwLock<ProjectionArg<P, V, D>>>
|
2021-11-07 07:16:33 +01:00
|
|
|
where V::Msg: Send + Sync,
|
2021-05-28 00:45:30 +02:00
|
|
|
D::IntoIter: Send + Sync + 'static
|
2021-05-22 01:33:58 +02:00
|
|
|
{
|
2021-08-24 23:15:18 +02:00
|
|
|
self.remove_arg(&arg_key);
|
|
|
|
|
2021-02-05 01:18:46 +01:00
|
|
|
let arg = Arc::new(RwLock::new(
|
|
|
|
ProjectionArg {
|
2021-05-13 23:46:22 +02:00
|
|
|
src: None,
|
2021-05-22 01:33:58 +02:00
|
|
|
notify: Box::new(notify),
|
|
|
|
proj: self.proj.clone(),
|
|
|
|
rx, tx
|
2021-02-05 01:18:46 +01:00
|
|
|
}));
|
|
|
|
|
2021-08-24 23:15:18 +02:00
|
|
|
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()));
|
2021-05-13 23:46:22 +02:00
|
|
|
|
|
|
|
arg
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
2021-08-24 23:15:18 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
2021-02-05 01:18:46 +01:00
|
|
|
/// Special Observer which can access the state of the projection on notify
|
2021-05-22 01:33:58 +02:00
|
|
|
/// also handles the reset()
|
|
|
|
pub struct ProjectionArg<P, V, D>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
V: View + ?Sized,
|
2021-02-05 01:18:46 +01:00
|
|
|
D: ChannelData<Item = V::Msg>,
|
|
|
|
D::IntoIter: Send + Sync
|
|
|
|
{
|
2021-05-13 23:46:22 +02:00
|
|
|
src: Option<Arc<V>>,
|
2021-05-22 01:33:58 +02:00
|
|
|
notify: Box<dyn Fn(&mut P, &V::Msg) + Send + Sync + 'static>,
|
|
|
|
proj: Arc<RwLock<Weak<RwLock<P>>>>,
|
|
|
|
rx: ChannelReceiver<D>,
|
|
|
|
tx: ChannelSender<D>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P, V, D> UpdateTask for ProjectionArg<P, V, D>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
V: View + ?Sized,
|
|
|
|
D: ChannelData<Item = V::Msg>,
|
2021-11-07 07:16:33 +01:00
|
|
|
D::IntoIter: Send + Sync
|
2021-05-22 01:33:58 +02:00
|
|
|
{
|
2021-06-05 23:01:32 +02:00
|
|
|
fn update(&self) {
|
2021-05-22 01:33:58 +02:00
|
|
|
if let Some(p) = self.proj.read().unwrap().upgrade() {
|
|
|
|
if let Some(data) = self.rx.try_recv() {
|
|
|
|
for msg in data {
|
2021-06-16 01:56:09 +02:00
|
|
|
//eprintln!("proj update {:?}", msg);
|
2021-05-22 01:33:58 +02:00
|
|
|
(self.notify)(
|
|
|
|
&mut *p.write().unwrap(),
|
|
|
|
&msg
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-06-16 01:56:09 +02:00
|
|
|
} else {
|
2021-11-18 22:55:32 +01:00
|
|
|
//eprintln!("proj update: upgrade fail");
|
2021-05-22 01:33:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P, V, D> UpdateTask for RwLock<ProjectionArg<P, V, D>>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
V: View + ?Sized,
|
|
|
|
D: ChannelData<Item = V::Msg>,
|
2021-11-07 07:16:33 +01:00
|
|
|
D::IntoIter: Send + Sync
|
2021-05-22 01:33:58 +02:00
|
|
|
{
|
|
|
|
fn update(&self) {
|
|
|
|
self.read().unwrap().update();
|
|
|
|
}
|
2021-02-05 01:18:46 +01:00
|
|
|
}
|
|
|
|
|
2021-01-22 14:56:56 +01:00
|
|
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
impl<P, Item, D> Observer<dyn SingletonView<Item = Item>> for ProjectionArg<P, dyn SingletonView<Item = Item>, D>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
D: ChannelData<Item = ()>,
|
2021-02-05 01:18:46 +01:00
|
|
|
D::IntoIter: Send + Sync
|
|
|
|
{
|
2021-01-22 14:56:56 +01:00
|
|
|
fn reset(&mut self, new_src: Option<Arc<dyn SingletonView<Item = Item>>>) {
|
2021-05-13 23:46:22 +02:00
|
|
|
self.src = new_src;
|
2021-01-22 14:56:56 +01:00
|
|
|
self.notify(&());
|
|
|
|
}
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
fn notify(&mut self, msg: &()) {
|
|
|
|
self.tx.send(msg.clone());
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
impl<P, Item, D> Observer<dyn SequenceView<Item = Item>> for ProjectionArg<P, dyn SequenceView<Item = Item>, D>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
D: ChannelData<Item = usize>,
|
2021-02-05 01:18:46 +01:00
|
|
|
D::IntoIter: Send + Sync
|
|
|
|
{
|
2021-01-22 14:56:56 +01:00
|
|
|
fn reset(&mut self, new_src: Option<Arc<dyn SequenceView<Item = Item>>>) {
|
|
|
|
let old_len = self.src.len().unwrap_or(0);
|
2021-05-13 23:46:22 +02:00
|
|
|
self.src = new_src;
|
2021-01-22 14:56:56 +01:00
|
|
|
let new_len = self.src.len().unwrap_or(0);
|
|
|
|
|
|
|
|
self.notify_each(0 .. max(old_len, new_len));
|
|
|
|
}
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
fn notify(&mut self, msg: &usize) {
|
|
|
|
self.tx.send(*msg);
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
|
|
|
|
2021-05-22 01:33:58 +02:00
|
|
|
impl<P, Key, Item, D> Observer<dyn IndexView<Key, Item = Item>> for ProjectionArg<P, dyn IndexView<Key, Item = Item>, D>
|
|
|
|
where P: Send + Sync + 'static,
|
|
|
|
Key: Clone + Send + Sync,
|
2021-11-07 07:16:33 +01:00
|
|
|
D: ChannelData<Item = IndexArea<Key>>,
|
2021-02-05 01:18:46 +01:00
|
|
|
D::IntoIter: Send + Sync
|
|
|
|
{
|
2021-01-22 14:56:56 +01:00
|
|
|
fn reset(&mut self, new_src: Option<Arc<dyn IndexView<Key, Item = Item>>>) {
|
|
|
|
let old_area = self.src.area();
|
2021-05-13 23:46:22 +02:00
|
|
|
self.src = new_src;
|
2021-01-22 14:56:56 +01:00
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
self.notify(&old_area);
|
|
|
|
self.notify(&self.src.area())
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
|
2021-11-07 07:16:33 +01:00
|
|
|
fn notify(&mut self, msg: &IndexArea<Key>) {
|
2021-05-22 01:33:58 +02:00
|
|
|
self.tx.send(msg.clone());
|
2021-01-22 14:56:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|