lib-nested/nested/src/terminal/compositor.rs

80 lines
2.1 KiB
Rust

use {
crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View},
index::{IndexArea, IndexView},
projection::ProjectionHelper,
terminal::{TerminalAtom, TerminalView},
},
cgmath::Point2,
std::sync::Arc,
std::sync::RwLock,
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct TerminalCompositor {
layers: Vec<Arc<dyn TerminalView>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self>,
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl TerminalCompositor {
pub fn new(port: InnerViewPort<dyn TerminalView>) -> Arc<RwLock<Self>> {
let comp = Arc::new(RwLock::new(TerminalCompositor {
layers: Vec::new(),
cast: port.get_broadcast(),
proj_helper: ProjectionHelper::new(port.0.update_hooks.clone()),
}));
comp.write().unwrap().proj_helper.set_proj(&comp);
port.set_view(Some(comp.clone()));
comp
}
pub fn push(&mut self, v: OuterViewPort<dyn TerminalView>) {
let idx = self.layers.len();
self.layers.push(
self.proj_helper
.new_index_arg(idx, v, |s: &mut Self, area| {
s.cast.notify(area);
}),
);
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl View for TerminalCompositor {
type Msg = IndexArea<Point2<i16>>;
}
impl IndexView<Point2<i16>> for TerminalCompositor {
type Item = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let mut atom = None;
for layer in self.layers.iter() {
match (atom, layer.get(pos)) {
(None, next) => atom = next,
(Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)),
_ => {}
}
}
atom
}
fn area(&self) -> IndexArea<Point2<i16>> {
let mut area = IndexArea::Empty;
for layer in self.layers.iter() {
area = area.union(layer.area());
}
area
}
}