From 7fdc0bf27293009849462f32a4bf517831e21610 Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sun, 7 Nov 2021 07:16:33 +0100 Subject: [PATCH] optimize index views with IndexArea enum to allow range based notifications --- nested/src/grid/flatten.rs | 122 ++++++++++++++------------- nested/src/grid/mod.rs | 124 +++++++++++++-------------- nested/src/grid/window_iterator.rs | 60 +++++++++++++ nested/src/index/buffer.rs | 13 ++- nested/src/index/map_item.rs | 18 ++-- nested/src/index/map_key.rs | 18 ++-- nested/src/index/mod.rs | 41 ++++++--- nested/src/leveled_term_view.rs | 94 --------------------- nested/src/lib.rs | 1 - nested/src/list/editor.rs | 45 +++++----- nested/src/list/sexpr.rs | 22 ++--- nested/src/projection.rs | 28 +++--- nested/src/sequence/seq2idx.rs | 27 +++--- nested/src/singleton/map.rs | 2 +- nested/src/singleton/to_index.rs | 17 ++-- nested/src/string_editor.rs | 1 - nested/src/terminal/compositor.rs | 33 +++----- nested/src/terminal/terminal.rs | 55 +++++++++--- rust-toolchain | 2 +- shell/src/ascii_box.rs | 33 +++++--- shell/src/box.rs | 131 ----------------------------- shell/src/main.rs | 76 +++++++---------- shell/src/process.rs | 4 - 23 files changed, 419 insertions(+), 548 deletions(-) create mode 100644 nested/src/grid/window_iterator.rs delete mode 100644 nested/src/leveled_term_view.rs delete mode 100644 shell/src/box.rs diff --git a/nested/src/grid/flatten.rs b/nested/src/grid/flatten.rs index 92c2dc2..b97e746 100644 --- a/nested/src/grid/flatten.rs +++ b/nested/src/grid/flatten.rs @@ -1,18 +1,19 @@ use { std::{ sync::Arc, + cmp::max, collections::HashMap }, std::sync::RwLock, cgmath::{Point2, Vector2}, crate::{ core::{ - View, Observer, ObserverBroadcast, ObserverExt, + View, Observer, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort, port::UpdateTask }, grid::{GridView, GridWindowIterator}, - index::IndexView, + index::{IndexArea, IndexView}, projection::ProjectionHelper } }; @@ -48,7 +49,7 @@ where Item: 'static impl View for Flatten where Item: 'static { - type Msg = Point2; + type Msg = IndexArea>; } impl IndexView> for Flatten @@ -57,13 +58,15 @@ where Item: 'static type Item = Item; fn get(&self, idx: &Point2) -> Option { - let chunk_idx = self.get_chunk_idx(*idx)?; - let chunk = self.chunks.get(&chunk_idx)?; + let chunk_idx = self.get_chunk_idx(*idx)?; + let chunk = self.chunks.get(&chunk_idx)?; chunk.view.get(&(*idx - chunk.offset)) } - fn area(&self) -> Option>> { - Some(GridWindowIterator::from(Point2::new(0, 0) .. self.limit).collect()) + fn area(&self) -> IndexArea> { + IndexArea::Range( + Point2::new(0, 0) ..= self.limit + ) } } @@ -83,8 +86,10 @@ where Item: 'static top: proj_helper.new_index_arg( Point2::new(-1, -1), top_port, - |s: &mut Self, chunk_idx| { - s.update_chunk(*chunk_idx); + |s: &mut Self, chunk_area| { + for chunk_idx in chunk_area.iter() { + s.update_chunk(chunk_idx); + } } ), chunks: HashMap::new(), @@ -104,20 +109,26 @@ where Item: 'static let view = self.proj_helper.new_index_arg( chunk_idx, chunk_port.clone(), - move |s: &mut Self, idx| { + move |s: &mut Self, area| { if let Some(chunk) = s.chunks.get(&chunk_idx) { - if chunk.limit != chunk.view.range().end { + if chunk.limit != *chunk.view.area().range().end() { s.update_all_offsets(); } } + if let Some(chunk) = s.chunks.get(&chunk_idx) { - s.cast.notify(&(idx + chunk.offset)); + s.cast.notify( + &area.map(|pt| pt + chunk.offset) + ); } } ); if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { chunk.view = view; + self.cast.notify( + &chunk.view.area().map(|pt| pt + chunk.offset) + ); } else { self.chunks.insert( chunk_idx, @@ -129,94 +140,91 @@ where Item: 'static ); } - chunk_port.0.update(); self.update_all_offsets(); - chunk_port.0.update(); } else { self.proj_helper.remove_arg(&chunk_idx); - let mut dirty_idx = Vec::new(); - if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { - dirty_idx.extend( - GridWindowIterator::from( - Point2::new(chunk.offset.x, chunk.offset.y) - .. Point2::new(chunk.offset.x + chunk.limit.x, chunk.offset.y + chunk.limit.y)) - ); + if let Some(chunk) = self.chunks.remove(&chunk_idx) { + self.update_all_offsets(); } - - self.chunks.remove(&chunk_idx); - self.cast.notify_each(dirty_idx); - self.update_all_offsets(); } } /// recalculate all chunk offsets /// and update size of flattened grid fn update_all_offsets(&mut self) { - let mut dirty_idx = Vec::new(); + let top_range = self.top.area().range(); + let mut col_widths = vec![0 as i16; (top_range.end().x+1) as usize]; + let mut row_heights = vec![0 as i16; (top_range.end().y+1) as usize]; - let top_range = self.top.range(); - let mut col_widths = vec![0 as i16; (top_range.end.x) as usize]; - let mut row_heights = vec![0 as i16; (top_range.end.y) as usize]; - - for chunk_idx in GridWindowIterator::from(self.top.range()) { + for chunk_idx in GridWindowIterator::from(top_range.clone()) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { - let lim = chunk.view.range().end; - col_widths[chunk_idx.x as usize] = std::cmp::max(col_widths[chunk_idx.x as usize], lim.x); - row_heights[chunk_idx.y as usize] = std::cmp::max(row_heights[chunk_idx.y as usize], lim.y); + let chunk_range = chunk.view.area().range(); + let lim = *chunk_range.end(); + + col_widths[chunk_idx.x as usize] = + max( + col_widths[chunk_idx.x as usize], + if lim.x < 0 { 0 } else { lim.x+1 } + ); + row_heights[chunk_idx.y as usize] = + max( + row_heights[chunk_idx.y as usize], + if lim.y < 0 { 0 } else { lim.y+1 } + ); } } - for chunk_idx in GridWindowIterator::from(self.top.range()) { + for chunk_idx in GridWindowIterator::from(top_range.clone()) { if let Some(chunk) = self.chunks.get_mut(&chunk_idx) { let old_offset = chunk.offset; let old_limit = chunk.limit; - chunk.limit = chunk.view.range().end; + chunk.limit = *chunk.view.area().range().end(); chunk.offset = Vector2::new( (0 .. chunk_idx.x as usize).map(|x| col_widths[x]).sum(), (0 .. chunk_idx.y as usize).map(|y| row_heights[y]).sum() ); +/* if old_offset != chunk.offset { - dirty_idx.extend( - GridWindowIterator::from( - Point2::new(std::cmp::min(old_offset.x, chunk.offset.x), - std::cmp::min(old_offset.y, chunk.offset.y)) - .. Point2::new(std::cmp::max(old_offset.x + old_limit.x, chunk.offset.x + chunk.limit.x), - std::cmp::max(old_offset.y + old_limit.y, chunk.offset.y + chunk.limit.y))) + self.cast.notify( + &IndexArea::Range( + Point2::new( + std::cmp::min(old_offset.x, chunk.offset.x), + std::cmp::min(old_offset.y, chunk.offset.y) + ) + ..= Point2::new( + std::cmp::max(old_offset.x + old_limit.x, chunk.offset.x + chunk.limit.x), + std::cmp::max(old_offset.y + old_limit.y, chunk.offset.y + chunk.limit.y) + ) + ) ); } +*/ } } let old_limit = self.limit; self.limit = Point2::new( - (0 .. top_range.end.x as usize).map(|x| col_widths[x]).sum(), - (0 .. top_range.end.y as usize).map(|y| row_heights[y]).sum() + (0 ..= top_range.end().x as usize).map(|x| col_widths[x]).sum::() - 1, + (0 ..= top_range.end().y as usize).map(|y| row_heights[y]).sum::() - 1, ); - // fixme: dirty hack to mitigate the buggy notifications, not efficien - dirty_idx.extend( - GridWindowIterator::from( - Point2::new(0, 0) .. Point2::new( - std::cmp::max(old_limit.x, self.limit.x), - std::cmp::max(old_limit.y, self.limit.y) - ) + self.cast.notify( + &IndexArea::Range( + Point2::new(0, 0) ..= Point2::new(max(self.limit.x, old_limit.x), max(self.limit.y, old_limit.y)) ) ); - - self.cast.notify_each(dirty_idx); } /// given an index in the flattened sequence, /// which sub-sequence does it belong to? fn get_chunk_idx(&self, glob_pos: Point2) -> Option> { - for chunk_idx in GridWindowIterator::from(self.top.range()) { + for chunk_idx in GridWindowIterator::from(self.top.area().range()) { if let Some(chunk) = self.chunks.get(&chunk_idx) { - let chunk_range = chunk.view.range(); - let end = chunk_range.end + chunk.offset; + let end = chunk.limit + chunk.offset; - if glob_pos.x < end.x && glob_pos.y < end.y { + if glob_pos.x <= end.x && glob_pos.y <= end.y { return Some(chunk_idx); } } diff --git a/nested/src/grid/mod.rs b/nested/src/grid/mod.rs index 29ea36d..e44592f 100644 --- a/nested/src/grid/mod.rs +++ b/nested/src/grid/mod.rs @@ -1,81 +1,81 @@ + use { std::{ - ops::{Range, RangeInclusive} + ops::RangeInclusive, + cmp::{min, max} }, cgmath::{Point2}, - crate::{ - index::{IndexView} - } + crate::index::{IndexArea, IndexView} }; -pub mod offset; -pub mod flatten; - //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> pub trait GridView = IndexView>; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -impl dyn GridView { - pub fn range(&self) -> Range> { - if let Some(area) = self.area() { - Point2::new( - area.iter().map(|p| p.x).min().unwrap_or(0), - area.iter().map(|p| p.y).min().unwrap_or(0) - ) .. - Point2::new( - area.iter().map(|p| p.x+1).max().unwrap_or(0), - area.iter().map(|p| p.y+1).max().unwrap_or(0) - ) - } else { - Point2::new(i16::MIN, i16::MIN) .. Point2::new(i16::MAX, i16::MAX) - } - } -} +pub mod offset; +pub mod flatten; +pub mod window_iterator; + +pub use window_iterator::GridWindowIterator; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -pub struct GridWindowIterator { - next: Point2, - range: Range> -} +impl IndexArea> { -impl From>> for GridWindowIterator { - fn from(range: Range>) -> Self { - GridWindowIterator { - next: range.start, - range - } - } -} - -impl From>> for GridWindowIterator { - fn from(range: RangeInclusive>) -> Self { - GridWindowIterator { - next: *range.start(), - range: *range.start() .. Point2::new(range.end().x+1, range.end().y+1) - } - } -} - -impl Iterator for GridWindowIterator { - type Item = Point2; - - fn next(&mut self) -> Option> { - if self.next.y < self.range.end.y { - let next = self.next; - - if self.next.x+1 < self.range.end.x { - self.next.x += 1; - } else { - self.next.x = self.range.start.x; - self.next.y += 1; - } - - Some(next) - } else { - None + // todo: this is not perfect (e.g. diagonals are inefficient) + pub fn iter(&self) -> GridWindowIterator { + GridWindowIterator::from(self.range()) + } + + pub fn range(&self) -> RangeInclusive> { + match self { + IndexArea::Empty => Point2::new(i16::MAX, i16::MAX) ..= Point2::new(i16::MIN, i16::MIN), + IndexArea::Full => panic!("range from full grid area"), + IndexArea::Set(v) => + Point2::new( + v.iter().map(|p| p.x).min().unwrap_or(0), + v.iter().map(|p| p.y).min().unwrap_or(0) + ) ..= + Point2::new( + v.iter().map(|p| p.x).max().unwrap_or(0), + v.iter().map(|p| p.y).max().unwrap_or(0) + ), + IndexArea::Range(r) => r.clone() + } + } + + pub fn union(self, other: IndexArea>) -> IndexArea> { + match (self, other) { + (IndexArea::Empty, a) | + (a, IndexArea::Empty) => a, + + (IndexArea::Full, _) | + (_, IndexArea::Full) => IndexArea::Full, + + (IndexArea::Set(mut va), IndexArea::Set(mut vb)) => { + va.extend(vb.into_iter()); + IndexArea::Set(va) + }, + + (IndexArea::Range(r), IndexArea::Set(mut v)) | + (IndexArea::Set(mut v), IndexArea::Range(r)) => { + v.extend(GridWindowIterator::from(r)); + IndexArea::Set(v) + }, + + (IndexArea::Range(ra), IndexArea::Range(rb)) => IndexArea::Range( + Point2::new( + min(ra.start().x, rb.start().x), + min(ra.start().y, rb.start().y) + ) + ..= + Point2::new( + max(ra.end().x, rb.end().x), + max(ra.end().y, rb.end().y) + ) + ) } } } diff --git a/nested/src/grid/window_iterator.rs b/nested/src/grid/window_iterator.rs new file mode 100644 index 0000000..b2f587e --- /dev/null +++ b/nested/src/grid/window_iterator.rs @@ -0,0 +1,60 @@ + +use { + std::ops::{Range, RangeInclusive}, + cgmath::{Point2} +}; + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +pub struct GridWindowIterator { + next: Point2, + range: Range> +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +impl From>> for GridWindowIterator { + fn from(range: Range>) -> Self { + GridWindowIterator { + next: range.start, + range + } + } +} + +impl From>> for GridWindowIterator { + fn from(range: RangeInclusive>) -> Self { + GridWindowIterator { + next: *range.start(), + range: *range.start() .. Point2::new(range.end().x+1, range.end().y+1) + } + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> + +impl Iterator for GridWindowIterator { + type Item = Point2; + + fn next(&mut self) -> Option> { + if self.next.y < self.range.end.y { + if self.next.x < self.range.end.x { + let next = self.next; + + if self.next.x+1 < self.range.end.x { + self.next.x += 1; + } else { + self.next.x = self.range.start.x; + self.next.y += 1; + } + + Some(next) + } else { + None + } + } else { + None + } + } +} + diff --git a/nested/src/index/buffer.rs b/nested/src/index/buffer.rs index f14beaf..43fa9be 100644 --- a/nested/src/index/buffer.rs +++ b/nested/src/index/buffer.rs @@ -13,7 +13,7 @@ use { View, InnerViewPort }, - index::IndexView + index::{IndexArea, IndexView} } }; @@ -25,7 +25,7 @@ impl View for IndexBufferView where Key: Clone + Hash + Eq + Send + Sync + 'static, Item: Clone + Send + Sync + 'static { - type Msg = Key; + type Msg = IndexArea; } impl IndexView for IndexBufferView @@ -38,12 +38,11 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static, self.0.read().unwrap().get(key).cloned() } - fn area(&self) -> Option> { - Some(self.0.read().unwrap().keys().cloned().collect()) + fn area(&self) -> IndexArea { + IndexArea::Set(self.0.read().unwrap().keys().cloned().collect()) } } - pub struct IndexBuffer where Key: Clone + Hash + Eq + Send + Sync + 'static, Item: Clone + Send + Sync + 'static @@ -68,7 +67,7 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static, pub fn insert(&mut self, key: Key, item: Item) { self.data.write().unwrap().insert(key.clone(), item); - self.cast.notify(&key); + self.cast.notify(&IndexArea::Set(vec![ key ])); } pub fn insert_iter(&mut self, iter: T) @@ -80,7 +79,7 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static, pub fn remove(&mut self, key: Key) { self.data.write().unwrap().remove(&key); - self.cast.notify(&key); + self.cast.notify(&IndexArea::Set(vec![ key ])); } } diff --git a/nested/src/index/map_item.rs b/nested/src/index/map_item.rs index f12f2c6..d9c5711 100644 --- a/nested/src/index/map_item.rs +++ b/nested/src/index/map_item.rs @@ -14,7 +14,7 @@ pub use { InnerViewPort, OuterViewPort }, - index::{IndexView} + index::{IndexArea, IndexView} } }; @@ -76,7 +76,7 @@ where Key: Clone + Send + Sync, SrcView: IndexView + ?Sized, F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync { - type Msg = Key; + type Msg = IndexArea; } impl IndexView for MapIndexItem @@ -90,7 +90,7 @@ where Key: Clone + Send + Sync, self.src_view.get(key).as_ref().map(|item| (self.f)(key, item)) } - fn area(&self) -> Option> { + fn area(&self) -> IndexArea { self.src_view.area() } } @@ -102,15 +102,15 @@ where Key: Clone + Send + Sync, { fn reset(&mut self, view: Option>) { let old_area = self.area(); - self.src_view = view; - let new_area = self.area(); - if let Some(area) = old_area { self.cast.notify_each(area); } - if let Some(area) = new_area { self.cast.notify_each(area); } + self.src_view = view; + + self.cast.notify(&old_area); + self.cast.notify(&self.src_view.area()) } - fn notify(&mut self, msg: &Key) { - self.cast.notify(msg); + fn notify(&mut self, area: &IndexArea) { + self.cast.notify(area); } } diff --git a/nested/src/index/map_key.rs b/nested/src/index/map_key.rs index 4635f4c..7ba392d 100644 --- a/nested/src/index/map_key.rs +++ b/nested/src/index/map_key.rs @@ -14,7 +14,7 @@ pub use { InnerViewPort, OuterViewPort }, - index::{IndexView}, + index::{IndexArea, IndexView}, grid::{GridView} } }; @@ -106,7 +106,7 @@ where DstKey: Clone + Send + Sync, F1: Fn(&SrcKey) -> DstKey + Send + Sync, F2: Fn(&DstKey) -> Option + Send + Sync, { - type Msg = DstKey; + type Msg = IndexArea; } impl IndexView for MapIndexKey @@ -122,8 +122,8 @@ where DstKey: Clone + Send + Sync, self.src_view.get(&(self.f2)(key)?) } - fn area(&self) -> Option> { - Some(self.src_view.area()?.iter().map(&self.f1).collect()) + fn area(&self) -> IndexArea { + self.src_view.area().map(&self.f1) } } @@ -137,14 +137,12 @@ where DstKey: Clone + Send + Sync, fn reset(&mut self, view: Option>) { let old_area = self.area(); self.src_view = view; - let new_area = self.area(); - - if let Some(area) = old_area { self.cast.notify_each(area); } - if let Some(area) = new_area { self.cast.notify_each(area); } + self.cast.notify(&old_area); + self.cast.notify(&self.area()); } - fn notify(&mut self, msg: &SrcKey) { - self.cast.notify(&(self.f1)(msg)); + fn notify(&mut self, msg: &IndexArea) { + self.cast.notify(&msg.map(&self.f1)); } } diff --git a/nested/src/index/mod.rs b/nested/src/index/mod.rs index f639ef7..ab656d0 100644 --- a/nested/src/index/mod.rs +++ b/nested/src/index/mod.rs @@ -6,7 +6,7 @@ pub mod buffer; use { std::{ sync::Arc, - ops::Deref, + ops::{Deref, RangeInclusive}, }, std::sync::RwLock, crate::core::View @@ -14,15 +14,34 @@ use { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -pub trait IndexView : View +#[derive(Clone)] +pub enum IndexArea { + Empty, + Full, + Set(Vec), + Range(RangeInclusive), + //Procedural(Arc Box>>) +} + +impl IndexArea { + pub fn map(&self, f: impl Fn(&Key) -> T) -> IndexArea { + match self { + IndexArea::Empty => IndexArea::Empty, + IndexArea::Full => IndexArea::Full, + IndexArea::Set(v) => IndexArea::Set(v.iter().map(&f).collect()), + IndexArea::Range(r) => IndexArea::Range(f(&r.start()) ..= f(&r.end())) + } + } +} + +pub trait IndexView : View> where Key: Send + Sync { type Item; fn get(&self, key: &Key) -> Option; - // todo: AreaIterator enum to switch between Allocated and Procedural area - fn area(&self) -> Option> { - None + fn area(&self) -> IndexArea { + IndexArea::Full } } @@ -38,7 +57,7 @@ where Key: Send + Sync, self.read().unwrap().get(key) } - fn area(&self) -> Option> { + fn area(&self) -> IndexArea { self.read().unwrap().area() } } @@ -53,7 +72,7 @@ where Key: Send + Sync, self.deref().get(key) } - fn area(&self) -> Option> { + fn area(&self) -> IndexArea { self.deref().area() } } @@ -68,17 +87,17 @@ where Key: Send + Sync, self.as_ref()?.get(key) } - fn area(&self) -> Option> { + fn area(&self) -> IndexArea { if let Some(v) = self.as_ref() { v.area() } else { - Some(Vec::new()) + IndexArea::Empty } } } //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - +/* pub trait ImplIndexView : Send + Sync { type Key : Send + Sync; type Value; @@ -104,4 +123,4 @@ impl IndexView for V { (self as &V).area() } } - +*/ diff --git a/nested/src/leveled_term_view.rs b/nested/src/leveled_term_view.rs deleted file mode 100644 index 919c6f8..0000000 --- a/nested/src/leveled_term_view.rs +++ /dev/null @@ -1,94 +0,0 @@ -use { - std::{ - sync::{Arc} - }, - std::sync::RwLock, - cgmath::Point2, - crate::{ - core::{ViewPort, Observer, ObserverExt, ObserverBroadcast, InnerViewPort, OuterViewPort}, - index::{ImplIndexView}, - terminal::{TerminalAtom, TerminalView, TerminalStyle}, - projection::{ProjectionHelper} - } -}; - -//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> - -pub struct LeveledTermView { - src: Arc>, - level: usize, - - cast: Arc>>, - proj_helper: ProjectionHelper<(), Self> -} - -impl LeveledTermView { - pub fn new( - src: OuterViewPort - ) -> (Arc>, OuterViewPort) { - let port = ViewPort::new(); - let v = Self::with_port(src, port.inner()); - (v, port.into_outer()) - } - - pub fn with_port( - src_port: OuterViewPort, - dst_port: InnerViewPort - ) -> Arc> { - let mut proj_helper = ProjectionHelper::new(dst_port.0.update_hooks.clone()); - - let v = Arc::new(RwLock::new( - LeveledTermView { - src: proj_helper.new_index_arg( - (), - src_port, - |p: &mut Self, pos: &Point2| { - p.cast.notify(pos); - }), - level: 0, - cast: dst_port.get_broadcast(), - proj_helper - } - )); - - v.write().unwrap().proj_helper.set_proj(&v); - dst_port.set_view(Some(v.clone())); - - v - } - - pub fn set_level(&mut self, l: usize) { - if self.level != l { - self.level = l; - - // update complete area - if let Some(a) = self.src.area() { - self.cast.notify_each(a); - } - } - } -} - -impl ImplIndexView for LeveledTermView { - type Key = Point2; - type Value = TerminalAtom; - - fn get(&self, pos: &Point2) -> Option { - self.src.get(pos).map( - |a| a.add_style_front( - if self.level > 1 { - TerminalStyle::bold(true) - .add(TerminalStyle::bg_color((0, 0, 0))) - } else if self.level > 0 { - TerminalStyle::bg_color((40, 40, 40)) - } else { - TerminalStyle::bold(false) - }) - ) - } - - fn area(&self) -> Option>> { - self.src.area() - } -} - diff --git a/nested/src/lib.rs b/nested/src/lib.rs index 7967491..611d921 100644 --- a/nested/src/lib.rs +++ b/nested/src/lib.rs @@ -15,7 +15,6 @@ pub mod list; pub mod tree_nav; pub mod string_editor; -pub mod leveled_term_view; pub mod bimap; diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index e3a48cd..e80d43a 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -3,22 +3,9 @@ use { termion::event::{Event, Key}, crate::{ core::{ - View, ViewPort, OuterViewPort, - InnerViewPort, - ObserverBroadcast, - Observer, - ObserverExt, - context::{ - ReprTree, - Object, - MorphismType, - MorphismMode, - Context - } }, - projection::ProjectionHelper, singleton::{SingletonView, SingletonBuffer}, sequence::{SequenceView}, vec::{VecBuffer}, @@ -30,7 +17,6 @@ use { TerminalEditorResult, make_label }, - leveled_term_view::LeveledTermView, list::{SExprView, ListDecoration, ListCursor, ListCursorMode, editor_view::{ListEditorView, ListEditorViewSegment}}, tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor} } @@ -61,6 +47,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, style: ListEditorStyle, level: usize, + cur_dist: Arc>, } impl TreeNav for ListEditor @@ -326,6 +313,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, tree_addr: vec![] } ); + *self.cur_dist.write().unwrap() += 1; } } TreeNavResult::Continue @@ -586,7 +574,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, } impl ListEditor -where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, FnMakeItemEditor: Fn() -> Arc> { pub fn get_seg_seq_view(&self) -> OuterViewPort>> { @@ -596,32 +584,39 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, self.data_port.outer().to_sequence().map(|ed| ed.read().unwrap().get_term_view()), segment_view_port.inner() ); + segment_view_port.into_outer() .map( - |segment| match segment { + move |segment| { + let cursor_col = (90, 60, 200); + match segment { ListEditorViewSegment::InsertCursor => make_label("|") .map_item( - |_pt, atom| - atom.add_style_back(TerminalStyle::fg_color((90,60,200))) - //.add_style_back(TerminalStyle::bg_color((0,0,0))) + move |_pt, atom| + atom.add_style_back(TerminalStyle::fg_color(cursor_col)) .add_style_back(TerminalStyle::bold(true)) ), ListEditorViewSegment::Select(sub_view) => sub_view.map_item( - |_pt, atom| - atom.add_style_front(TerminalStyle::bg_color((90,60,200))) + move |_pt, atom| { + let old_col = atom.style.bg_color.unwrap_or(cursor_col); + atom.add_style_front(TerminalStyle::bg_color(((old_col.0 as f32 * 0.4) as u8, (old_col.1 as f32 * 0.4) as u8, (old_col.2 as f32 * 0.4) as u8))) + } ), ListEditorViewSegment::Modify(sub_view) => { sub_view.clone().map_item( - |_pt, atom| - atom.add_style_back(TerminalStyle::bg_color((22,15,50))) + move |_pt, atom| { + let old_col = atom.style.bg_color.unwrap_or(cursor_col); + atom.add_style_front(TerminalStyle::bg_color(((old_col.0 as f32 * 0.4) as u8, (old_col.1 as f32 * 0.4) as u8, (old_col.2 as f32 * 0.4) as u8))) + } //.add_style_back(TerminalStyle::bold(true)) ) }, ListEditorViewSegment::View(sub_view) => sub_view.clone() } + } ) } @@ -644,6 +639,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, self.get_seg_seq_view() .decorate("\"", "\"", "", 1) .to_grid_horizontal() + .flatten() } @@ -681,7 +677,8 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, style, make_item_editor, - level: 0 + level: 0, + cur_dist: Arc::new(RwLock::new(0)) }; le.set_style(style); le diff --git a/nested/src/list/sexpr.rs b/nested/src/list/sexpr.rs index ec4f09f..7aa37d0 100644 --- a/nested/src/list/sexpr.rs +++ b/nested/src/list/sexpr.rs @@ -3,6 +3,7 @@ use { core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort}, projection::ProjectionHelper, sequence::SequenceView, + index::{IndexArea}, terminal::{make_label, TerminalStyle, TerminalView}, }, cgmath::Point2, @@ -141,19 +142,16 @@ pub struct VerticalSexprDecorator { } impl View for VerticalSexprDecorator { - type Msg = Point2; + type Msg = IndexArea>; } impl IndexView> for VerticalSexprDecorator { type Item = OuterViewPort; - fn area(&self) -> Option>> { - let mut area = (0..self.items.len()?) - .map(|i| Point2::new(1 as i16, i as i16)) - .collect::>(); - area.push(Point2::new(0, 0)); - area.push(Point2::new(2, self.items.len()? as i16 - 1)); - Some(area) + fn area(&self) -> IndexArea> { + IndexArea::Range( + Point2::new(0, 0) ..= Point2::new(2, std::cmp::max(self.items.len().unwrap() as i16 - 1, 0)) + ) } fn get(&self, pt: &Point2) -> Option { @@ -218,9 +216,11 @@ impl VerticalSexprDecorator { opening_port: make_label(opening), closing_port: make_label(closing), items: proj_helper.new_sequence_arg((), items_port, |s: &mut Self, item_idx| { - s.cast.notify(&Point2::new(1, *item_idx as i16)); - s.cast.notify(&Point2::new(2, *item_idx as i16 - 1)); - s.cast.notify(&Point2::new(2, *item_idx as i16)); + s.cast.notify( + &IndexArea::Range( + Point2::new(0, *item_idx as i16) ..= Point2::new(2, *item_idx as i16) + ) + ); }), list_style: TerminalStyle::fg_color(match level { 0 => (200, 120, 10), diff --git a/nested/src/projection.rs b/nested/src/projection.rs index 7ab80bd..ffd6995 100644 --- a/nested/src/projection.rs +++ b/nested/src/projection.rs @@ -16,12 +16,13 @@ use { channel::{ ChannelSender, ChannelReceiver, ChannelData, - set_channel + set_channel, + queue_channel } }, singleton::{SingletonView}, sequence::{SequenceView}, - index::{IndexView} + index::{IndexArea, IndexView} } }; @@ -75,13 +76,13 @@ where ArgKey: Clone + Hash + Eq, port.get_view_arc() } - pub fn new_index_arg( + pub fn new_index_arg( &mut self, arg_key: ArgKey, port: OuterViewPort>, - notify: impl Fn(&mut P, &Key) + Send + Sync + 'static + notify: impl Fn(&mut P, &IndexArea) + Send + Sync + 'static ) -> Arc>>>> { - port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, set_channel())); + port.add_observer(self.new_arg(arg_key, Arc::new(port.0.clone()), notify, queue_channel())); port.get_view_arc() } @@ -96,7 +97,7 @@ where ArgKey: Clone + Hash + Eq, (tx, rx): (ChannelSender, ChannelReceiver) ) -> Arc>> - where V::Msg: Send + Sync + std::fmt::Debug, + where V::Msg: Send + Sync, D::IntoIter: Send + Sync + 'static { self.remove_arg(&arg_key); @@ -151,8 +152,7 @@ impl UpdateTask for ProjectionArg where P: Send + Sync + 'static, V: View + ?Sized, D: ChannelData, - D::IntoIter: Send + Sync, -V::Msg: std::fmt::Debug + D::IntoIter: Send + Sync { fn update(&self) { if let Some(p) = self.proj.read().unwrap().upgrade() { @@ -175,8 +175,7 @@ impl UpdateTask for RwLock> where P: Send + Sync + 'static, V: View + ?Sized, D: ChannelData, - D::IntoIter: Send + Sync, -V::Msg: std::fmt::Debug + D::IntoIter: Send + Sync { fn update(&self) { self.read().unwrap().update(); @@ -225,19 +224,18 @@ where P: Send + Sync + 'static, impl Observer> for ProjectionArg, D> where P: Send + Sync + 'static, Key: Clone + Send + Sync, - D: ChannelData, + D: ChannelData>, D::IntoIter: Send + Sync { fn reset(&mut self, new_src: Option>>) { let old_area = self.src.area(); self.src = new_src; - let new_area = self.src.area(); - if let Some(area) = old_area { self.notify_each(area); } - if let Some(area) = new_area { self.notify_each(area); } + self.notify(&old_area); + self.notify(&self.src.area()) } - fn notify(&mut self, msg: &Key) { + fn notify(&mut self, msg: &IndexArea) { self.tx.send(msg.clone()); } } diff --git a/nested/src/sequence/seq2idx.rs b/nested/src/sequence/seq2idx.rs index 17df9e7..530c33e 100644 --- a/nested/src/sequence/seq2idx.rs +++ b/nested/src/sequence/seq2idx.rs @@ -5,11 +5,11 @@ use { std::sync::RwLock, crate::{ core::{ - View, Observer, ObserverExt, ObserverBroadcast, + View, Observer, ObserverBroadcast, ViewPort, InnerViewPort, OuterViewPort }, sequence::SequenceView, - index::IndexView, + index::{IndexArea, IndexView}, grid::GridView } }; @@ -56,7 +56,7 @@ impl OuterViewPort> { impl View for Sequence2Index where SrcView: SequenceView + ?Sized + 'static { - type Msg = usize; + type Msg = IndexArea; } impl IndexView for Sequence2Index @@ -67,8 +67,16 @@ where SrcView: SequenceView + ?Sized + 'static { self.src_view.get(key) } - fn area(&self) -> Option> { - Some((0 .. self.src_view.len()?).collect()) + fn area(&self) -> IndexArea { + if let Some(len) = self.src_view.len() { + if len > 0 { + IndexArea::Range(0 ..= len-1) + } else { + IndexArea::Empty + } + } else { + IndexArea::Full + } } } @@ -77,14 +85,13 @@ where SrcView: SequenceView + ?Sized + 'static { fn reset(&mut self, view: Option>) { let old_area = self.area(); self.src_view = view; - let new_area = self.area(); - if let Some(area) = old_area { self.cast.notify_each(area); } - if let Some(area) = new_area { self.cast.notify_each(area); } + self.cast.notify(&old_area); + self.cast.notify(&self.area()); } - fn notify(&mut self, msg: &usize) { - self.cast.notify(msg); + fn notify(&mut self, idx: &usize) { + self.cast.notify(&IndexArea::Set(vec![ *idx ])); } } diff --git a/nested/src/singleton/map.rs b/nested/src/singleton/map.rs index e97802a..1f88a45 100644 --- a/nested/src/singleton/map.rs +++ b/nested/src/singleton/map.rs @@ -4,7 +4,7 @@ use { crate::{ singleton::{SingletonView}, core::{ - Observer, ObserverExt, ObserverBroadcast, + Observer, ObserverBroadcast, View, ViewPort, OuterViewPort } } diff --git a/nested/src/singleton/to_index.rs b/nested/src/singleton/to_index.rs index 28372af..3cf4991 100644 --- a/nested/src/singleton/to_index.rs +++ b/nested/src/singleton/to_index.rs @@ -3,10 +3,10 @@ use { std::sync::RwLock, crate::{ singleton::{SingletonView}, - index::{IndexView}, + index::{IndexArea, IndexView}, grid::{GridView}, core::{ - Observer, ObserverExt, ObserverBroadcast, + Observer, ObserverBroadcast, View, ViewPort, OuterViewPort } } @@ -52,7 +52,7 @@ where SrcView: SingletonView + ?Sized impl View for Singleton2Index where SrcView: SingletonView + ?Sized { - type Msg = (); + type Msg = IndexArea<()>; } impl IndexView<()> for Singleton2Index @@ -60,9 +60,10 @@ where SrcView: SingletonView + ?Sized { type Item = SrcView::Item; - fn area(&self) -> Option> { - Some(vec![()]) + fn area(&self) -> IndexArea<()> { + IndexArea::Full } + fn get(&self, _msg: &()) -> Option { Some(self.src_view.as_ref().unwrap().get()) } @@ -75,11 +76,11 @@ where SrcView: SingletonView + ?Sized { fn reset(&mut self, view: Option>) { self.src_view = view; - self.cast.notify(&()); + self.cast.notify(&IndexArea::Full); } - fn notify(&mut self, msg: &()) { - self.cast.notify(msg); + fn notify(&mut self, _: &()) { + self.cast.notify(&IndexArea::Full); } } diff --git a/nested/src/string_editor.rs b/nested/src/string_editor.rs index 4eae28e..8a3bcb1 100644 --- a/nested/src/string_editor.rs +++ b/nested/src/string_editor.rs @@ -6,7 +6,6 @@ use { core::{ViewPort, OuterViewPort}, singleton::{SingletonView, SingletonBuffer}, sequence::{SequenceView}, - vec::VecBuffer, terminal::{TerminalView, TerminalStyle, TerminalEvent, TerminalEditor, TerminalEditorResult}, list::{ListEditor, sexpr::ListDecoration}, tree_nav::{TreeNav, TreeNavResult, TreeCursor} diff --git a/nested/src/terminal/compositor.rs b/nested/src/terminal/compositor.rs index 6c92f0f..ad4c2c6 100644 --- a/nested/src/terminal/compositor.rs +++ b/nested/src/terminal/compositor.rs @@ -5,8 +5,8 @@ use { std::sync::RwLock, cgmath::Point2, crate::{ - core::{InnerViewPort, OuterViewPort, Observer, ObserverBroadcast}, - index::{ImplIndexView}, + core::{InnerViewPort, OuterViewPort, View, Observer, ObserverBroadcast}, + index::{IndexArea, IndexView}, terminal::{TerminalAtom, TerminalView}, projection::ProjectionHelper } @@ -46,8 +46,8 @@ impl TerminalCompositor { self.proj_helper.new_index_arg( idx, v, - |s: &mut Self, pos| { - s.cast.notify(pos); + |s: &mut Self, area| { + s.cast.notify(area); } ) ); @@ -56,9 +56,12 @@ impl TerminalCompositor { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>> -impl ImplIndexView for TerminalCompositor { - type Key = Point2; - type Value = TerminalAtom; +impl View for TerminalCompositor { + type Msg = IndexArea>; +} + +impl IndexView> for TerminalCompositor { + type Item = TerminalAtom; fn get(&self, pos: &Point2) -> Option { let mut atom = None; @@ -74,21 +77,11 @@ impl ImplIndexView for TerminalCompositor { atom } - fn area(&self) -> Option>> { - let mut area = Some(Vec::new()); + fn area(&self) -> IndexArea> { + let mut area = IndexArea::Empty; for layer in self.layers.iter() { - if let ( - Some(mut new_area), - Some(area) - ) = ( - layer.area(), - area.as_mut() - ) { - area.append(&mut new_area); - } else { - area = None; - } + area = area.union(layer.area()); } area diff --git a/nested/src/terminal/terminal.rs b/nested/src/terminal/terminal.rs index b34bf1c..d143586 100644 --- a/nested/src/terminal/terminal.rs +++ b/nested/src/terminal/terminal.rs @@ -27,6 +27,7 @@ use { set_channel } }, + index::{IndexArea}, grid::{GridWindowIterator} }, super::{ @@ -119,24 +120,40 @@ struct TermOutObserver { writer: Arc } +impl TermOutObserver { + fn send_area(&mut self, area: IndexArea>) { + match area { + IndexArea::Empty => {}, + IndexArea::Full => { + let (w, h) = termion::terminal_size().unwrap(); + for pos in GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(w as i16, h as i16)) { + self.dirty_pos_tx.send(pos); + } + } + IndexArea::Range(r) => { + for pos in GridWindowIterator::from(r) { + self.dirty_pos_tx.send(pos); + } + } + IndexArea::Set(v) => { + for pos in v { + self.dirty_pos_tx.send(pos); + } + } + } + } +} + impl Observer for TermOutObserver { fn reset(&mut self, view: Option>) { self.writer.reset(); - - let (w, h) = termion::terminal_size().unwrap(); if let Some(view) = view { - for pos in view.area().unwrap_or( - GridWindowIterator::from( - Point2::new(0, 0) .. Point2::new(w as i16, h as i16) - ).collect() - ) { - self.dirty_pos_tx.send(pos); - } + self.send_area(view.area()); } } - fn notify(&mut self, pos: &Point2) { - self.dirty_pos_tx.send(*pos); + fn notify(&mut self, area: &IndexArea>) { + self.send_area(area.clone()); } } @@ -166,10 +183,24 @@ impl TermOutWriter { // draw atoms until view port is destroyed while let Some(dirty_pos) = self.dirty_pos_rx.recv().await { + let (w, h) = termion::terminal_size().unwrap(); + if let Some(view) = self.view.read().unwrap().as_ref() { let mut out = self.out.write().unwrap(); - for pos in dirty_pos.into_iter().filter(|p| p.x >= 0 && p.y >= 0) { + let d = dirty_pos.into_iter().filter(|p| p.x >= 0 && p.y >= 0 && p.x < w as i16 && p.y < w as i16);//.collect::>(); + /* + d.sort_by(|a,b| { + if a.y < b.y { + std::cmp::Ordering::Less + } else if a.y == b.y { + a.x.cmp(&b.x) + } else { + std::cmp::Ordering::Greater + } + }); +*/ + for pos in d { if pos != cur_pos { write!(out, "{}", termion::cursor::Goto(pos.x as u16 + 1, pos.y as u16 + 1))?; } diff --git a/rust-toolchain b/rust-toolchain index 5841773..ea2cce1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,5 +5,5 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "nightly-2021-09-29" +channel = "nightly-2021-10-26" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/shell/src/ascii_box.rs b/shell/src/ascii_box.rs index 11b20c4..83f014e 100644 --- a/shell/src/ascii_box.rs +++ b/shell/src/ascii_box.rs @@ -13,7 +13,7 @@ use{ ObserverBroadcast, context::{ReprTree, Object, MorphismType, MorphismMode, Context}, port::{UpdateTask}}, - index::{IndexView}, + index::{IndexArea, IndexView}, grid::{GridWindowIterator}, terminal::{ Terminal, @@ -57,14 +57,19 @@ impl AsciiBox { if self.extent != new_extent { let old_extent = self.extent; self.extent = new_extent; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(2+std::cmp::max(old_extent.x, new_extent.x), 2+std::cmp::max(old_extent.y, new_extent.y)))); + self.cast.notify( + &IndexArea::Range( + Point2::new(0, 0) ..= + Point2::new( + 1+std::cmp::max(old_extent.x, new_extent.x), + 1+std::cmp::max(old_extent.y, new_extent.y)))); } } pub fn fit_content(&mut self) { if let Some(c) = self.content.as_ref() { - let p = c.range().end; - self.resize(Vector2::new(p.x, p.y)); + let p = *c.area().range().end(); + self.resize(Vector2::new(p.x+1, p.y+1)); } else { self.resize(Vector2::new(0, 0)); } @@ -74,17 +79,17 @@ impl AsciiBox { impl Observer for AsciiBox { fn reset(&mut self, new_content: Option>) { self.content = new_content; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2))); + self.fit_content(); } - fn notify(&mut self, pt: &Point2) { - self.cast.notify(&(pt + Vector2::new(1, 1))); + fn notify(&mut self, area: &IndexArea>) { + self.cast.notify(&area.map(|pt| pt + Vector2::new(1, 1))); self.fit_content(); } } impl View for AsciiBox { - type Msg = Point2; + type Msg = IndexArea>; } impl IndexView> for AsciiBox { @@ -114,19 +119,19 @@ impl IndexView> for AsciiBox { None } } else if + pt.x > 0 && + pt.y > 0 && pt.x < self.extent.x+1 && pt.y < self.extent.y+1 { - self.content.get(&(pt - Vector2::new(1, 1))) + Some(self.content.get(&(pt - Vector2::new(1, 1))).unwrap_or(TerminalAtom::from(' '))) } else { None } } - fn area(&self) -> Option>> { - Some(GridWindowIterator::from( - Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2) - ).collect()) + fn area(&self) -> IndexArea> { + IndexArea::Range(Point2::new(0, 0) ..= Point2::new(1,1)+self.extent) } - } + diff --git a/shell/src/box.rs b/shell/src/box.rs deleted file mode 100644 index 5d895f4..0000000 --- a/shell/src/box.rs +++ /dev/null @@ -1,131 +0,0 @@ - -use{ - std::sync::{Arc, RwLock}, - cgmath::{Point2, Vector2}, - nested::{ - core::{ - View, - ViewPort, - InnerViewPort, - OuterViewPort, - Observer, - ObserverExt, - ObserverBroadcast, - context::{ReprTree, Object, MorphismType, MorphismMode, Context}, - port::{UpdateTask}}, - index::{IndexView}, - grid::{GridWindowIterator}, - terminal::{ - Terminal, - TerminalStyle, - TerminalAtom, - TerminalCompositor, - TerminalEvent, - make_label, - TerminalView, - TerminalEditor}, - } -}; - -pub struct AsciiBox { - content: Option>, - extent: Vector2, - - cast: Arc>> -} - -impl AsciiBox { - pub fn new( - extent: Vector2, - content_port: OuterViewPort, - output_port: InnerViewPort - ) -> Arc> { - let ascii_box = Arc::new(RwLock::new(AsciiBox { - content: None, - extent, - cast: output_port.get_broadcast() - })); - - output_port.0.update_hooks.write().unwrap().push(Arc::new(content_port.0.clone())); - output_port.set_view(Some(ascii_box.clone())); - content_port.add_observer(ascii_box.clone()); - - ascii_box - } - - pub fn resize(&mut self, new_extent: Vector2) { - if self.extent != new_extent { - let old_extent = self.extent; - self.extent = new_extent; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(2+std::cmp::max(old_extent.x, new_extent.x), 2+std::cmp::max(old_extent.y, new_extent.y)))); - } - } - - pub fn fit_content(&mut self) { - if let Some(c) = self.content.as_ref() { - let p = c.range().end; - self.resize(Vector2::new(p.x, p.y)); - } else { - self.resize(Vector2::new(0, 0)); - } - } -} - -impl Observer for AsciiBox { - fn reset(&mut self, new_content: Option>) { - self.content = new_content; - self.notify_each(GridWindowIterator::from(Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2))); - } - - fn notify(&mut self, pt: &Point2) { - self.cast.notify(&(pt + Vector2::new(1, 1))); - } -} - -impl View for AsciiBox { - type Msg = Point2; -} - -impl IndexView> for AsciiBox { - type Item = TerminalAtom; - - fn get(&self, pt: &Point2) -> Option { - if pt.x == 0 || pt.x == self.extent.x+1 { - // vertical line - if pt.y == 0 && pt.x == 0 { - Some(TerminalAtom::from('╭')) - } else if pt.y == 0 && pt.x == self.extent.x+1 { - Some(TerminalAtom::from('╮')) - } else if pt.y > 0 && pt.y < self.extent.y+1 { - Some(TerminalAtom::from('│')) - } else if pt.y == self.extent.y+1 && pt.x == 0 { - Some(TerminalAtom::from('╰')) - } else if pt.y == self.extent.y+1 && pt.x == self.extent.x+1 { - Some(TerminalAtom::from('╯')) - } else { - None - } - } else if pt.y == 0 || pt.y == self.extent.y+1 { - // horizontal line - if pt.x > 0 && pt.x < self.extent.x+1 { - Some(TerminalAtom::from('─')) - } else { - None - } - } else if - pt.x < self.extent.x+1 && - pt.y < self.extent.y+1 - { - self.content.get(&(pt - Vector2::new(1, 1))) - } else { - None - } - } - - fn area(&self) -> Option>> { - Some(GridWindowIterator::from( - Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2) - ).collect()) - } - -} diff --git a/shell/src/main.rs b/shell/src/main.rs index 79bc16d..c53f5ab 100644 --- a/shell/src/main.rs +++ b/shell/src/main.rs @@ -21,7 +21,7 @@ use{ ObserverBroadcast, context::{ReprTree, Object, MorphismType, MorphismMode, Context}, port::{UpdateTask}}, - index::{IndexView}, + index::{IndexView, IndexArea}, grid::{GridWindowIterator}, sequence::{SequenceView, SequenceViewExt}, vec::{VecBuffer}, @@ -44,6 +44,24 @@ use{ } }; +struct TestView {} + +impl View for TestView { + type Msg = IndexArea>; +} + +impl IndexView> for TestView { + type Item = TerminalAtom; + + fn get(&self, pt: &Point2) -> Option { + Some(TerminalAtom::from('.')) + } + + fn area(&self) -> IndexArea> { + IndexArea::Full + } +} + #[async_std::main] async fn main() { let term_port = ViewPort::new(); @@ -99,35 +117,22 @@ async fn main() { tree_addr: vec![ 0 ] }); - loop { - term_port.update(); - /* - if let Some(p) = pty.as_mut() { - if p.get_status() { - if let Some(ptybox) = ptybox.take() { - ptybox.write().unwrap().fit_content(); - } - pty = None; - process_list_editor.up(); + let tp = term_port.clone(); + async_std::task::spawn( + async move { + loop { + tp.update(); + async_std::task::sleep(std::time::Duration::from_millis(10)).await; } } -*/ - term_port.update(); - + ); + + loop { let ev = term.next_event().await; -/* - if let Some(pty) = pty.as_mut() { - pty.handle_terminal_event(&ev); - } else { -*/ match ev { TerminalEvent::Resize(new_size) => { cur_size.set(new_size); - term_port.inner().get_broadcast().notify_each( - nested::grid::GridWindowIterator::from( - Point2::new(0,0) .. Point2::new(new_size.x, new_size.y) - ) - ); + term_port.inner().get_broadcast().notify(&IndexArea::Full); } TerminalEvent::Input(Event::Key(Key::Ctrl('c'))) | TerminalEvent::Input(Event::Key(Key::Ctrl('g'))) | @@ -157,27 +162,7 @@ async fn main() { process_list_editor.goto_end(); } TerminalEvent::Input(Event::Key(Key::Char('\n'))) => { - //let mut output_port = ViewPort::new(); process_list_editor.get_item().unwrap().write().unwrap().launch_pty2(); -/* - let box_port = ViewPort::new(); - let test_box = AsciiBox::new( - Vector2::new(80, 25), - output_port.outer() - .map_item(|_,a| a.add_style_back(TerminalStyle::fg_color((230, 230, 230)))), - box_port.inner() - ); - - ptybox = Some(test_box.clone()); - - table_buf.remove(Point2::new(0, y-1)); - - let mut p = box_port.outer().map_item(|_idx, x| x.add_style_back(TerminalStyle::fg_color((90, 120, 100))) .offset(Vector2::new(0, -1)); - table_port.update_hooks.write().unwrap().push(Arc::new(p.clone().0)); - - y += 1; - table_buf.insert(Point2::new(0, y), p.clone()); -*/ } ev => { @@ -229,7 +214,8 @@ async fn main() { } } - //drop(term); + drop(term); + drop(term_port); } ); diff --git a/shell/src/process.rs b/shell/src/process.rs index 0bb63fc..70b3d6c 100644 --- a/shell/src/process.rs +++ b/shell/src/process.rs @@ -134,10 +134,6 @@ impl ProcessLauncher { pub fn launch_pty2(&mut self) { self.launch_pty(self.pty_port.inner()); - //self.ptybox.write().unwrap().fit_content(); - - //let mut p = - //table_port.update_hooks.write().unwrap().push(Arc::new(p.clone().0)); } pub fn launch_pty(&mut self, port: InnerViewPort) -> Option {