use projection helper in terminal compositor

This commit is contained in:
Michael Sippel 2021-02-17 18:18:39 +01:00
parent 4485b3cf13
commit eb6dc43e53
Signed by: senvas
GPG key ID: F96CF119C34B64A6
2 changed files with 191 additions and 155 deletions

View file

@ -10,7 +10,7 @@ pub mod terminal;
pub mod projection; pub mod projection;
pub mod string_editor; pub mod string_editor;
pub mod leveled_term_view; pub mod leveled_term_view;
pub mod cell_layout; //pub mod cell_layout;
use { use {
async_std::{task}, async_std::{task},
@ -39,13 +39,69 @@ use {
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
/*
struct ListView {
opening: OuterViewPort<dyn SequenceView<Item = TerminalAtom>>,
closing: OuterViewPort<dyn SequenceView<Item = TerminalAtom>>,
delim: OuterViewPort<dyn SequenceView<Item = TerminalAtom>>,
data: Option<Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>>,
cast: Arc<RwLock<ObserverBroadcast<>>
}
impl View for ListView {
type Msg = usize;
}
impl SequenceView for ListView {
type Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>;
fn get(&self, idx: usize) -> Option<Self::Item> {
let len = self.data.len();
if idx == 0 {
Some(self.opening.clone())
} else if idx < len*2 {
if idx % 2 == 1 {
self.data.get(idx / 2)
} else {
Some(self.delim.clone())
}
} else if idx == len*2 {
Some(self.closing.clone())
} else {
None
}
}
}
impl Observer<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>> for ListView {
fn reset(&mut self, v: Option<Arc<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>>) {
self.data = v;
}
fn notify(&self, idx: usize) {
}
}
impl ListView {
fn new(
data: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>,
port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>>
) -> Self {
let
}
}
*/
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
let term_port = ViewPort::<dyn TerminalView>::new(); let term_port = ViewPort::<dyn TerminalView>::new();
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();
@ -60,33 +116,10 @@ async fn main() {
let window_size_port = ViewPort::new(); let window_size_port = ViewPort::new();
let mut window_size = SingletonBuffer::new(Vector2::new(0, 0), window_size_port.inner()); let mut window_size = SingletonBuffer::new(Vector2::new(0, 0), window_size_port.inner());
let opening_port = ViewPort::new();
let mut opening = VecBuffer::new(opening_port.inner());
let delim_port = ViewPort::new();
let mut delim = VecBuffer::new(delim_port.inner());
let closing_port = ViewPort::new();
let mut closing = VecBuffer::new(closing_port.inner());
let e1_port = ViewPort::new();
let mut e1 = VecBuffer::new(e1_port.inner());
let e2_port = ViewPort::new();
let mut e2 = VecBuffer::new(e2_port.inner());
opening.push(TerminalAtom::new('[', TerminalStyle::fg_color((180, 120, 80))));
delim.push(TerminalAtom::new(',', TerminalStyle::fg_color((180, 120, 80))));
delim.push(TerminalAtom::new(' ', TerminalStyle::fg_color((180, 120, 80))));
closing.push(TerminalAtom::new(']', TerminalStyle::fg_color((180, 120, 80))));
let str_list_port = ViewPort::new(); let str_list_port = ViewPort::new();
let mut str_list = VecBuffer::<OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>::new(str_list_port.inner()); let mut str_list = VecBuffer::<OuterViewPort<dyn SequenceView<Item = TerminalAtom>>>::new(str_list_port.inner());
str_list.push(opening_port.outer().to_sequence()); compositor.write().unwrap().push(
str_list.push(closing_port.outer().to_sequence());
compositor.push(
str_list_port.outer() str_list_port.outer()
.to_sequence() .to_sequence()
.flatten() .flatten()
@ -99,54 +132,83 @@ async fn main() {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
// welcome message // welcome message
task::sleep(std::time::Duration::from_millis(500)).await; task::spawn(async move {
str_list.insert(1, e1_port.outer().to_sequence()); let opening_port = ViewPort::new();
for c in "Welcome!".chars() { let mut opening = VecBuffer::new(opening_port.inner());
e1.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255))));
let delim_port = ViewPort::new();
let mut delim = VecBuffer::new(delim_port.inner());
let closing_port = ViewPort::new();
let mut closing = VecBuffer::new(closing_port.inner());
let e1_port = ViewPort::new();
let mut e1 = VecBuffer::new(e1_port.inner());
let e2_port = ViewPort::new();
let mut e2 = VecBuffer::new(e2_port.inner());
opening.push(TerminalAtom::new('[', TerminalStyle::fg_color((180, 120, 80))));
delim.push(TerminalAtom::new(',', TerminalStyle::fg_color((180, 120, 80))));
delim.push(TerminalAtom::new(' ', TerminalStyle::fg_color((180, 120, 80))));
closing.push(TerminalAtom::new(']', TerminalStyle::fg_color((180, 120, 80))));
str_list.push(opening_port.outer().to_sequence());
str_list.push(closing_port.outer().to_sequence());
task::sleep(std::time::Duration::from_millis(500)).await;
str_list.insert(1, e1_port.outer().to_sequence());
for c in "Welcome!".chars() {
e1.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255))));
task::sleep(std::time::Duration::from_millis(80)).await;
}
task::sleep(std::time::Duration::from_millis(500)).await;
str_list.insert(2, delim_port.outer().to_sequence());
str_list.insert(3, e2_port.outer().to_sequence());
task::sleep(std::time::Duration::from_millis(80)).await; task::sleep(std::time::Duration::from_millis(80)).await;
} for c in "This is a flattened SequenceView.".chars() {
task::sleep(std::time::Duration::from_millis(500)).await; e2.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255))));
str_list.insert(2, delim_port.outer().to_sequence()); task::sleep(std::time::Duration::from_millis(80)).await;
str_list.insert(3, e2_port.outer().to_sequence()); }
task::sleep(std::time::Duration::from_millis(80)).await;
for c in "This is a flattened SequenceView.".chars() {
e2.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255))));
task::sleep(std::time::Duration::from_millis(80)).await;
}
task::sleep(std::time::Duration::from_millis(500)).await; task::sleep(std::time::Duration::from_millis(500)).await;
let l2_port = ViewPort::new(); let l2_port = ViewPort::new();
let mut l2 = VecBuffer::new(l2_port.inner()); let mut l2 = VecBuffer::new(l2_port.inner());
*str_list.get_mut(1) = l2_port.outer().to_sequence().flatten(); *str_list.get_mut(1) = l2_port.outer().to_sequence().flatten();
l2.push(opening_port.outer().to_sequence()); l2.push(opening_port.outer().to_sequence());
e1.clear(); e1.clear();
l2.push(e1_port.outer().to_sequence()); l2.push(e1_port.outer().to_sequence());
l2.push(closing_port.outer().to_sequence()); l2.push(closing_port.outer().to_sequence());
for c in "they can even be NeStEd!".chars() { for c in "they can even be NeStEd!".chars() {
e1.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255)))); e1.push(TerminalAtom::new(c, TerminalStyle::fg_color((180, 180, 255))));
task::sleep(std::time::Duration::from_millis(80)).await; task::sleep(std::time::Duration::from_millis(80)).await;
} }
for i in 0 .. 10 { loop {
task::sleep(std::time::Duration::from_millis(100)).await; for i in 0 .. 10 {
task::sleep(std::time::Duration::from_millis(60)).await;
let col = (100+10*i, 55+20*i, 20+ 20*i); let col = (100+10*i, 55+20*i, 20+ 20*i);
*opening.get_mut(0) = TerminalAtom::new('{', TerminalStyle::fg_color(col)); *opening.get_mut(0) = TerminalAtom::new('{', TerminalStyle::fg_color(col));
*closing.get_mut(0) = TerminalAtom::new('}', TerminalStyle::fg_color(col)); *closing.get_mut(0) = TerminalAtom::new('}', TerminalStyle::fg_color(col));
} }
for i in 0 .. 10 { for i in 0 .. 10 {
task::sleep(std::time::Duration::from_millis(100)).await; task::sleep(std::time::Duration::from_millis(60)).await;
let col = (100+10*i, 55+20*i, 20+ 20*i); let col = (100+10*i, 55+20*i, 20+ 20*i);
*opening.get_mut(0) = TerminalAtom::new('<', TerminalStyle::fg_color(col)); *opening.get_mut(0) = TerminalAtom::new('<', TerminalStyle::fg_color(col));
*closing.get_mut(0) = TerminalAtom::new('>', TerminalStyle::fg_color(col)); *closing.get_mut(0) = TerminalAtom::new('>', TerminalStyle::fg_color(col));
} }
}
});
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
// string editor 1 // string editor 1
@ -158,6 +220,22 @@ async fn main() {
let mut editor2 = StringEditor::new(); let mut editor2 = StringEditor::new();
let (leveled_edit2_view, leveled_edit2_view_port) = LeveledTermView::new(editor2.insert_view()); let (leveled_edit2_view, leveled_edit2_view_port) = LeveledTermView::new(editor2.insert_view());
compositor.write().unwrap().push(
leveled_edit_view_port
.map_key(
|p| p + Vector2::new(1, 1),
|p| Some(p - Vector2::new(1, 1))
)
);
compositor.write().unwrap().push(
leveled_edit2_view_port
.map_key(
|p| p + Vector2::new(1, 2),
|p| Some(p - Vector2::new(1, 2))
)
);
/*\ /*\
<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> <<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>

View file

@ -7,68 +7,65 @@ use {
crate::{ crate::{
core::{InnerViewPort, OuterViewPort, Observer, ObserverExt, ObserverBroadcast}, core::{InnerViewPort, OuterViewPort, Observer, ObserverExt, ObserverBroadcast},
index::{ImplIndexView}, index::{ImplIndexView},
terminal::{TerminalAtom, TerminalView} terminal::{TerminalAtom, TerminalView},
projection::ProjectionHelper
} }
}; };
struct CompositeLayer { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
comp: Weak<RwLock<TerminalCompositeView>>,
idx: usize pub struct TerminalCompositor {
layers: Vec<Arc<dyn TerminalView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<Self>
} }
impl Observer<dyn TerminalView> for CompositeLayer { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
let comp = self.comp.upgrade().unwrap();
let mut c = comp.write().unwrap();
let v = &mut c.layers.get_mut(&self.idx).unwrap().1; impl TerminalCompositor {
let old_view = v.clone(); pub fn new(
*v = view.clone(); port: InnerViewPort<dyn TerminalView>
drop(v); ) -> Arc<RwLock<Self>> {
let comp = Arc::new(RwLock::new(
if let Some(old_view) = old_view { TerminalCompositor {
if let Some(area) = old_view.area() { layers: Vec::new(),
c.cast.notify_each(area); cast: port.get_broadcast(),
proj_helper: ProjectionHelper::new()
} }
} ));
if let Some(view) = view.as_ref() { comp.write().unwrap().proj_helper.set_proj(&comp);
if let Some(area) = view.area() { port.set_view(Some(comp.clone()));
c.cast.notify_each(area);
} comp
}
} }
fn notify(&self, pos: &Point2<i16>) { pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
self.comp self.layers.push(
.upgrade().unwrap() self.proj_helper.new_index_arg(
.read().unwrap() v,
.cast.notify(pos); |s: &mut Self, pos| {
s.cast.notify(pos);
}
)
);
} }
} }
pub struct TerminalCompositeView { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
idx_count: usize,
layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
}
impl ImplIndexView for TerminalCompositeView { impl ImplIndexView for TerminalCompositor {
type Key = Point2<i16>; type Key = Point2<i16>;
type Value = TerminalAtom; type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> { fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let mut atom = None; let mut atom = None;
for idx in 0 .. self.idx_count { for layer in self.layers.iter() {
if let Some(l) = self.layers.get(&idx) { match (atom, layer.get(pos)) {
if let Some(view) = l.1.as_ref() { (None, next) => atom = next,
match (atom, view.get(pos)) { (Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)),
(None, next) => atom = next, _ => {}
(Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)),
_ => {}
}
}
} }
} }
@ -78,19 +75,17 @@ impl ImplIndexView for TerminalCompositeView {
fn area(&self) -> Option<Vec<Point2<i16>>> { fn area(&self) -> Option<Vec<Point2<i16>>> {
let mut area = Some(Vec::new()); let mut area = Some(Vec::new());
for (_, layer) in self.layers.iter() { for layer in self.layers.iter() {
if let Some(view) = layer.1.as_ref() { if let (
if let ( Some(mut new_area),
Some(mut new_area), Some(area)
Some(area) ) = (
) = ( layer.area(),
view.area(), area.as_mut()
area.as_mut() ) {
) { area.append(&mut new_area);
area.append(&mut new_area); } else {
} else { area = None;
area = None;
}
} }
} }
@ -98,40 +93,3 @@ impl ImplIndexView for TerminalCompositeView {
} }
} }
pub struct TerminalCompositor {
view: Arc<RwLock<TerminalCompositeView>>
}
impl TerminalCompositor {
pub fn new(
port: InnerViewPort<dyn TerminalView>
) -> Self {
let view = Arc::new(RwLock::new(
TerminalCompositeView {
idx_count: 0,
layers: HashMap::new(),
cast: port.get_broadcast()
}
));
port.set_view(Some(view.clone()));
TerminalCompositor{ view }
}
pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
let mut comp = self.view.write().unwrap();
let idx = comp.idx_count;
comp.idx_count += 1;
let layer = Arc::new(RwLock::new(CompositeLayer {
comp: Arc::downgrade(&self.view),
idx: idx
}));
comp.layers.insert(idx, (layer.clone(), None));
drop(comp);
v.add_observer(layer);
}
}