lib-nested/src/terminal/compositor.rs

138 lines
3.5 KiB
Rust
Raw Normal View History

use {
2021-01-06 21:35:46 +01:00
std::{
sync::{Arc, Weak, RwLock},
2021-01-16 16:09:16 +01:00
collections::HashMap
2021-01-06 21:35:46 +01:00
},
cgmath::Point2,
crate::{
2021-01-16 16:09:16 +01:00
core::{InnerViewPort, OuterViewPort, Observer, ObserverExt, ObserverBroadcast},
index::{ImplIndexView},
2021-01-06 21:35:46 +01:00
terminal::{TerminalAtom, TerminalView}
}
};
2021-01-06 21:35:46 +01:00
struct CompositeLayer {
comp: Weak<RwLock<TerminalCompositeView>>,
idx: usize
}
2021-01-06 21:35:46 +01:00
impl Observer<dyn TerminalView> for CompositeLayer {
fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
2021-01-06 21:35:46 +01:00
let comp = self.comp.upgrade().unwrap();
let mut c = comp.write().unwrap();
2021-01-16 16:09:16 +01:00
let v = &mut c.layers.get_mut(&self.idx).unwrap().1;
2021-01-16 15:31:37 +01:00
let old_view = v.clone();
*v = view.clone();
drop(v);
2021-01-06 21:35:46 +01:00
2021-01-16 15:31:37 +01:00
if let Some(old_view) = old_view {
if let Some(area) = old_view.area() {
c.cast.notify_each(area);
2021-01-06 21:35:46 +01:00
}
}
2021-01-16 15:31:37 +01:00
if let Some(view) = view.as_ref() {
if let Some(area) = view.area() {
c.cast.notify_each(area);
}
}
2021-01-06 21:35:46 +01:00
}
fn notify(&self, pos: &Point2<i16>) {
self.comp
.upgrade().unwrap()
.read().unwrap()
.cast.notify(pos);
}
}
pub struct TerminalCompositeView {
idx_count: usize,
layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>,
2021-01-06 21:35:46 +01:00
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
}
2021-01-06 21:35:46 +01:00
impl ImplIndexView for TerminalCompositeView {
type Key = Point2<i16>;
type Value = TerminalAtom;
2021-01-06 21:35:46 +01:00
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let mut atom = None;
for idx in 0 .. self.idx_count {
if let Some(l) = self.layers.get(&idx) {
if let Some(view) = l.1.as_ref() {
2021-01-06 21:35:46 +01:00
match (atom, view.get(pos)) {
(None, next) => atom = next,
(Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)),
_ => {}
}
}
}
}
2021-01-06 21:35:46 +01:00
atom
}
fn area(&self) -> Option<Vec<Point2<i16>>> {
let mut area = Some(Vec::new());
for (_, layer) in self.layers.iter() {
if let Some(view) = layer.1.as_ref() {
if let (
Some(mut new_area),
Some(area)
) = (
view.area(),
area.as_mut()
) {
area.append(&mut new_area);
} else {
area = None;
}
}
}
area
}
2021-01-06 21:35:46 +01:00
}
pub struct TerminalCompositor {
2021-01-16 16:09:16 +01:00
view: Arc<RwLock<TerminalCompositeView>>
2021-01-06 21:35:46 +01:00
}
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()));
2021-01-16 16:09:16 +01:00
TerminalCompositor{ view }
2021-01-06 21:35:46 +01:00
}
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 {
2021-01-06 21:35:46 +01:00
comp: Arc::downgrade(&self.view),
idx: idx
}));
2021-01-06 21:35:46 +01:00
comp.layers.insert(idx, (layer.clone(), None));
2021-01-06 21:35:46 +01:00
drop(comp);
v.add_observer(layer);
}
}