map_item() projection for index views
This commit is contained in:
parent
9c21ddbda1
commit
f3fa8a7af1
3 changed files with 143 additions and 10 deletions
105
src/index/map_item.rs
Normal file
105
src/index/map_item.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
pub use {
|
||||
std::{
|
||||
sync::{Arc, RwLock},
|
||||
ops::Range
|
||||
},
|
||||
crate::{
|
||||
core::{
|
||||
View,
|
||||
Observer,
|
||||
ObserverBroadcast,
|
||||
ViewPort,
|
||||
InnerViewPort,
|
||||
OuterViewPort
|
||||
},
|
||||
index::{IndexView}
|
||||
}
|
||||
};
|
||||
|
||||
impl<Key: 'static, Item: 'static> OuterViewPort<dyn IndexView<Key, Item = Item>> {
|
||||
pub fn map_item<
|
||||
DstItem: Default + 'static,
|
||||
F: Fn(&Item) -> DstItem + Send + Sync + 'static
|
||||
>(
|
||||
&self,
|
||||
f: F
|
||||
) -> OuterViewPort<dyn IndexView<Key, Item = DstItem>> {
|
||||
let port = ViewPort::new();
|
||||
let map = MapIndexItem::new(port.inner(), f);
|
||||
self.add_observer(map.clone());
|
||||
port.into_outer()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapIndexItem<Key, DstItem, SrcView, F>
|
||||
where SrcView: IndexView<Key> + ?Sized,
|
||||
F: Fn(&SrcView::Item) -> DstItem + Send + Sync
|
||||
{
|
||||
src_view: Option<Arc<SrcView>>,
|
||||
f: F,
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Key, Item = DstItem>>>>
|
||||
}
|
||||
|
||||
impl<Key, DstItem, SrcView, F> MapIndexItem<Key, DstItem, SrcView, F>
|
||||
where Key: 'static,
|
||||
DstItem: Default + 'static,
|
||||
SrcView: IndexView<Key> + ?Sized + 'static,
|
||||
F: Fn(&SrcView::Item) -> DstItem + Send + Sync + 'static
|
||||
{
|
||||
fn new(
|
||||
port: InnerViewPort<dyn IndexView<Key, Item = DstItem>>,
|
||||
f: F
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let map = Arc::new(RwLock::new(
|
||||
MapIndexItem {
|
||||
src_view: None,
|
||||
f,
|
||||
cast: port.get_broadcast()
|
||||
}
|
||||
));
|
||||
|
||||
port.set_view(Some(map.clone()));
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key, DstItem, SrcView, F> View for MapIndexItem<Key, DstItem, SrcView, F>
|
||||
where SrcView: IndexView<Key> + ?Sized,
|
||||
F: Fn(&SrcView::Item) -> DstItem + Send + Sync
|
||||
{
|
||||
type Msg = Key;
|
||||
}
|
||||
|
||||
impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
|
||||
where DstItem: Default,
|
||||
SrcView: IndexView<Key> + ?Sized,
|
||||
F: Fn(&SrcView::Item) -> DstItem + Send + Sync
|
||||
{
|
||||
type Item = DstItem;
|
||||
|
||||
fn get(&self, key: &Key) -> Self::Item {
|
||||
if let Some(v) = self.src_view.as_ref() {
|
||||
(self.f)(&v.get(key))
|
||||
} else {
|
||||
DstItem::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn range(&self) -> Option<Range<Key>> {
|
||||
self.src_view.as_ref()?.range()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
|
||||
where SrcView: IndexView<Key> + ?Sized,
|
||||
F: Fn(&SrcView::Item) -> DstItem + Send + Sync
|
||||
{
|
||||
fn reset(&mut self, view: Option<Arc<SrcView>>) {
|
||||
// todo: notify on reset ??
|
||||
self.src_view = view;
|
||||
}
|
||||
|
||||
fn notify(&self, msg: &Key) {
|
||||
self.cast.notify(msg);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
pub mod map_item;
|
||||
|
||||
use {
|
||||
std::{
|
||||
sync::{Arc, RwLock},
|
||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -2,15 +2,14 @@
|
|||
#![feature(assoc_char_funcs)]
|
||||
|
||||
pub mod core;
|
||||
pub mod view;
|
||||
pub mod index;
|
||||
pub mod grid;
|
||||
pub mod sequence;
|
||||
pub mod singleton;
|
||||
pub mod terminal;
|
||||
|
||||
pub mod string_editor;
|
||||
|
||||
//pub mod singleton_buffer;
|
||||
//pub mod vec_buffer;
|
||||
//pub mod sequence_element_projection;
|
||||
|
||||
use {
|
||||
async_std::{task},
|
||||
std::{
|
||||
|
@ -21,7 +20,7 @@ use {
|
|||
termion::event::{Event, Key},
|
||||
crate::{
|
||||
core::{View, Observer, ObserverExt, ViewPort},
|
||||
view::{*},
|
||||
index::{ImplIndexView},
|
||||
terminal::{
|
||||
TerminalView,
|
||||
TerminalAtom,
|
||||
|
@ -30,6 +29,7 @@ use {
|
|||
Terminal,
|
||||
TerminalCompositor
|
||||
},
|
||||
grid::GridOffset
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -107,10 +107,36 @@ async fn main() {
|
|||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
\*/
|
||||
|
||||
compositor.push(ViewPort::<dyn TerminalView>::with_view(Arc::new(Checkerboard)).into_outer());
|
||||
let offset_port = ViewPort::<dyn TerminalView>::new();
|
||||
let o = GridOffset::new(offset_port.inner());
|
||||
|
||||
let checkerboard_port = ViewPort::<dyn TerminalView>::with_view(Arc::new(Checkerboard));
|
||||
checkerboard_port.add_observer(o.clone());
|
||||
|
||||
compositor.push(offset_port.into_outer());
|
||||
|
||||
let edit_port = ViewPort::<dyn TerminalView>::new();
|
||||
let mut editor = string_editor::StringEditor::new(edit_port.inner());
|
||||
compositor.push(edit_port.into_outer());
|
||||
|
||||
let edit_offset_port = ViewPort::<dyn TerminalView>::new();
|
||||
let edit_o = GridOffset::new(edit_offset_port.inner());
|
||||
edit_port.add_observer(edit_o.clone());
|
||||
|
||||
compositor.push(
|
||||
edit_offset_port
|
||||
.into_outer()
|
||||
// add a nice black background
|
||||
.map_item(|atom| atom.map(
|
||||
|a| a.add_style_back(TerminalStyle::bg_color((0,0,0))))));
|
||||
|
||||
edit_o.write().unwrap().set_offset(Vector2::new(40, 4));
|
||||
|
||||
task::spawn(async move {
|
||||
for x in 0 .. 20 {
|
||||
async_std::task::sleep(std::time::Duration::from_millis(15)).await;
|
||||
o.write().unwrap().set_offset(Vector2::new(x as i16, x as i16));
|
||||
}
|
||||
});
|
||||
|
||||
/*\
|
||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
|
Loading…
Reference in a new issue