2020-12-09 17:31:08 +01:00
|
|
|
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,
|
2020-12-09 17:31:08 +01:00
|
|
|
crate::{
|
2021-01-16 16:09:16 +01:00
|
|
|
core::{InnerViewPort, OuterViewPort, Observer, ObserverExt, ObserverBroadcast},
|
2021-01-12 23:09:46 +01:00
|
|
|
index::{ImplIndexView},
|
2021-01-06 21:35:46 +01:00
|
|
|
terminal::{TerminalAtom, TerminalView}
|
2020-12-09 17:31:08 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-01-06 21:35:46 +01:00
|
|
|
struct CompositeLayer {
|
|
|
|
comp: Weak<RwLock<TerminalCompositeView>>,
|
2021-01-11 01:18:32 +01:00
|
|
|
idx: usize
|
2020-12-09 17:31:08 +01:00
|
|
|
}
|
|
|
|
|
2021-01-06 21:35:46 +01:00
|
|
|
impl Observer<dyn TerminalView> for CompositeLayer {
|
2021-01-11 01:18:32 +01:00
|
|
|
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,
|
2021-01-11 01:18:32 +01:00
|
|
|
layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>,
|
2021-01-06 21:35:46 +01:00
|
|
|
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
|
|
|
|
}
|
2020-12-09 17:31:08 +01:00
|
|
|
|
2021-01-06 21:35:46 +01:00
|
|
|
impl ImplIndexView for TerminalCompositeView {
|
|
|
|
type Key = Point2<i16>;
|
2021-01-16 20:19:52 +01:00
|
|
|
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) {
|
2021-01-11 01:18:32 +01:00
|
|
|
if let Some(view) = l.1.as_ref() {
|
2021-01-06 21:35:46 +01:00
|
|
|
match (atom, view.get(pos)) {
|
2020-12-09 17:31:08 +01:00
|
|
|
(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
|
2020-12-09 17:31:08 +01:00
|
|
|
}
|
|
|
|
|
2021-01-16 13:57:06 +01:00
|
|
|
fn area(&self) -> Option<Vec<Point2<i16>>> {
|
2021-01-16 18:00:56 +01:00
|
|
|
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
|
2020-12-09 17:31:08 +01:00
|
|
|
}
|
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;
|
|
|
|
|
2021-01-11 01:18:32 +01:00
|
|
|
let layer = Arc::new(RwLock::new(CompositeLayer {
|
2021-01-06 21:35:46 +01:00
|
|
|
comp: Arc::downgrade(&self.view),
|
2021-01-11 01:18:32 +01:00
|
|
|
idx: idx
|
|
|
|
}));
|
2021-01-06 21:35:46 +01:00
|
|
|
|
2021-01-11 01:18:32 +01:00
|
|
|
comp.layers.insert(idx, (layer.clone(), None));
|
2021-01-06 21:35:46 +01:00
|
|
|
drop(comp);
|
|
|
|
|
|
|
|
v.add_observer(layer);
|
2020-12-09 17:31:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|