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 {
|
use {
|
||||||
std::{
|
std::{
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -2,15 +2,14 @@
|
||||||
#![feature(assoc_char_funcs)]
|
#![feature(assoc_char_funcs)]
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod view;
|
pub mod index;
|
||||||
|
pub mod grid;
|
||||||
|
pub mod sequence;
|
||||||
|
pub mod singleton;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
|
|
||||||
pub mod string_editor;
|
pub mod string_editor;
|
||||||
|
|
||||||
//pub mod singleton_buffer;
|
|
||||||
//pub mod vec_buffer;
|
|
||||||
//pub mod sequence_element_projection;
|
|
||||||
|
|
||||||
use {
|
use {
|
||||||
async_std::{task},
|
async_std::{task},
|
||||||
std::{
|
std::{
|
||||||
|
@ -21,7 +20,7 @@ use {
|
||||||
termion::event::{Event, Key},
|
termion::event::{Event, Key},
|
||||||
crate::{
|
crate::{
|
||||||
core::{View, Observer, ObserverExt, ViewPort},
|
core::{View, Observer, ObserverExt, ViewPort},
|
||||||
view::{*},
|
index::{ImplIndexView},
|
||||||
terminal::{
|
terminal::{
|
||||||
TerminalView,
|
TerminalView,
|
||||||
TerminalAtom,
|
TerminalAtom,
|
||||||
|
@ -30,6 +29,7 @@ use {
|
||||||
Terminal,
|
Terminal,
|
||||||
TerminalCompositor
|
TerminalCompositor
|
||||||
},
|
},
|
||||||
|
grid::GridOffset
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ impl ImplIndexView for ScrambleBackground {
|
||||||
type Value = Option<TerminalAtom>;
|
type Value = Option<TerminalAtom>;
|
||||||
|
|
||||||
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
|
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
|
||||||
if ((pos.x/2) % 2 == 0) ^ ( pos.y % 2 == 0 ) {
|
if ((pos.x/2) % 2 == 0) ^ (pos.y % 2 == 0) {
|
||||||
Some(TerminalAtom::new(char::from((35+(5*pos.y+pos.x)%40) as u8), TerminalStyle::fg_color((40, 40, 40))))
|
Some(TerminalAtom::new(char::from((35+(5*pos.y+pos.x)%40) as u8), TerminalStyle::fg_color((40, 40, 40))))
|
||||||
} else {
|
} else {
|
||||||
Some(TerminalAtom::new(char::from((35+(pos.y+9*pos.x)%40) as u8), TerminalStyle::fg_color((90, 90, 90))))
|
Some(TerminalAtom::new(char::from((35+(pos.y+9*pos.x)%40) as u8), TerminalStyle::fg_color((90, 90, 90))))
|
||||||
|
@ -96,7 +96,7 @@ async fn main() {
|
||||||
|
|
||||||
let mut compositor = TerminalCompositor::new(term_port.inner());
|
let mut compositor = TerminalCompositor::new(term_port.inner());
|
||||||
compositor.push(ViewPort::<dyn TerminalView>::with_view(Arc::new(ScrambleBackground)).into_outer());
|
compositor.push(ViewPort::<dyn TerminalView>::with_view(Arc::new(ScrambleBackground)).into_outer());
|
||||||
|
|
||||||
let mut term = Terminal::new(term_port.outer());
|
let mut term = Terminal::new(term_port.outer());
|
||||||
let term_writer = term.get_writer();
|
let term_writer = term.get_writer();
|
||||||
|
|
||||||
|
@ -107,11 +107,37 @@ 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 edit_port = ViewPort::<dyn TerminalView>::new();
|
||||||
let mut editor = string_editor::StringEditor::new(edit_port.inner());
|
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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/*\
|
/*\
|
||||||
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||||
Event Loop
|
Event Loop
|
||||||
|
|
Loading…
Reference in a new issue