optimize index views with IndexArea enum to allow range based notifications

This commit is contained in:
Michael Sippel 2021-11-07 07:16:33 +01:00
parent bfd27fa3fa
commit 7fdc0bf272
Signed by: senvas
GPG key ID: F96CF119C34B64A6
23 changed files with 419 additions and 548 deletions

View file

@ -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<Item> View for Flatten<Item>
where Item: 'static
{
type Msg = Point2<i16>;
type Msg = IndexArea<Point2<i16>>;
}
impl<Item> IndexView<Point2<i16>> for Flatten<Item>
@ -62,8 +63,10 @@ where Item: 'static
chunk.view.get(&(*idx - chunk.offset))
}
fn area(&self) -> Option<Vec<Point2<i16>>> {
Some(GridWindowIterator::from(Point2::new(0, 0) .. self.limit).collect())
fn area(&self) -> IndexArea<Point2<i16>> {
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::<i16>() - 1,
(0 ..= top_range.end().y as usize).map(|y| row_heights[y]).sum::<i16>() - 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<i16>) -> Option<Point2<i16>> {
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);
}
}

View file

@ -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<Point2<i16>>;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl<Item> dyn GridView<Item = Item> {
pub fn range(&self) -> Range<Point2<i16>> {
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<i16>,
range: Range<Point2<i16>>
}
impl IndexArea<Point2<i16>> {
impl From<Range<Point2<i16>>> for GridWindowIterator {
fn from(range: Range<Point2<i16>>) -> Self {
GridWindowIterator {
next: range.start,
range
}
}
}
impl From<RangeInclusive<Point2<i16>>> for GridWindowIterator {
fn from(range: RangeInclusive<Point2<i16>>) -> 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<i16>;
fn next(&mut self) -> Option<Point2<i16>> {
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<Point2<i16>> {
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<Point2<i16>>) -> IndexArea<Point2<i16>> {
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)
)
)
}
}
}

View file

@ -0,0 +1,60 @@
use {
std::ops::{Range, RangeInclusive},
cgmath::{Point2}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct GridWindowIterator {
next: Point2<i16>,
range: Range<Point2<i16>>
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl From<Range<Point2<i16>>> for GridWindowIterator {
fn from(range: Range<Point2<i16>>) -> Self {
GridWindowIterator {
next: range.start,
range
}
}
}
impl From<RangeInclusive<Point2<i16>>> for GridWindowIterator {
fn from(range: RangeInclusive<Point2<i16>>) -> 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<i16>;
fn next(&mut self) -> Option<Point2<i16>> {
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
}
}
}

View file

@ -13,7 +13,7 @@ use {
View,
InnerViewPort
},
index::IndexView
index::{IndexArea, IndexView}
}
};
@ -25,7 +25,7 @@ impl<Key, Item> View for IndexBufferView<Key, Item>
where Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static
{
type Msg = Key;
type Msg = IndexArea<Key>;
}
impl<Key, Item> IndexView<Key> for IndexBufferView<Key, Item>
@ -38,12 +38,11 @@ where Key: Clone + Hash + Eq + Send + Sync + 'static,
self.0.read().unwrap().get(key).cloned()
}
fn area(&self) -> Option<Vec<Key>> {
Some(self.0.read().unwrap().keys().cloned().collect())
fn area(&self) -> IndexArea<Key> {
IndexArea::Set(self.0.read().unwrap().keys().cloned().collect())
}
}
pub struct IndexBuffer<Key, Item>
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<T>(&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 ]));
}
}

View file

@ -14,7 +14,7 @@ pub use {
InnerViewPort,
OuterViewPort
},
index::{IndexView}
index::{IndexArea, IndexView}
}
};
@ -76,7 +76,7 @@ where Key: Clone + Send + Sync,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&Key, &SrcView::Item) -> DstItem + Send + Sync
{
type Msg = Key;
type Msg = IndexArea<Key>;
}
impl<Key, DstItem, SrcView, F> IndexView<Key> for MapIndexItem<Key, DstItem, SrcView, F>
@ -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<Vec<Key>> {
fn area(&self) -> IndexArea<Key> {
self.src_view.area()
}
}
@ -102,15 +102,15 @@ where Key: Clone + Send + Sync,
{
fn reset(&mut self, view: Option<Arc<SrcView>>) {
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<Key>) {
self.cast.notify(area);
}
}

View file

@ -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<SrcKey> + Send + Sync,
{
type Msg = DstKey;
type Msg = IndexArea<DstKey>;
}
impl<DstKey, SrcKey, SrcView, F1, F2> IndexView<DstKey> for MapIndexKey<DstKey, SrcKey, SrcView, F1, F2>
@ -122,8 +122,8 @@ where DstKey: Clone + Send + Sync,
self.src_view.get(&(self.f2)(key)?)
}
fn area(&self) -> Option<Vec<DstKey>> {
Some(self.src_view.area()?.iter().map(&self.f1).collect())
fn area(&self) -> IndexArea<DstKey> {
self.src_view.area().map(&self.f1)
}
}
@ -137,14 +137,12 @@ where DstKey: Clone + Send + Sync,
fn reset(&mut self, view: Option<Arc<SrcView>>) {
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<SrcKey>) {
self.cast.notify(&msg.map(&self.f1));
}
}

View file

@ -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<Key> : View<Msg = Key>
#[derive(Clone)]
pub enum IndexArea<Key> {
Empty,
Full,
Set(Vec<Key>),
Range(RangeInclusive<Key>),
//Procedural(Arc<dyn Fn() -> Box<dyn Iterator<Item = Key>>>)
}
impl<Key> IndexArea<Key> {
pub fn map<T>(&self, f: impl Fn(&Key) -> T) -> IndexArea<T> {
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<Key> : View<Msg = IndexArea<Key>>
where Key: Send + Sync {
type Item;
fn get(&self, key: &Key) -> Option<Self::Item>;
// todo: AreaIterator enum to switch between Allocated and Procedural area
fn area(&self) -> Option<Vec<Key>> {
None
fn area(&self) -> IndexArea<Key> {
IndexArea::Full
}
}
@ -38,7 +57,7 @@ where Key: Send + Sync,
self.read().unwrap().get(key)
}
fn area(&self) -> Option<Vec<Key>> {
fn area(&self) -> IndexArea<Key> {
self.read().unwrap().area()
}
}
@ -53,7 +72,7 @@ where Key: Send + Sync,
self.deref().get(key)
}
fn area(&self) -> Option<Vec<Key>> {
fn area(&self) -> IndexArea<Key> {
self.deref().area()
}
}
@ -68,17 +87,17 @@ where Key: Send + Sync,
self.as_ref()?.get(key)
}
fn area(&self) -> Option<Vec<Key>> {
fn area(&self) -> IndexArea<Key> {
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<V: ImplIndexView> IndexView<V::Key> for V {
(self as &V).area()
}
}
*/

View file

@ -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<RwLock<dyn TerminalView>>,
level: usize,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<(), Self>
}
impl LeveledTermView {
pub fn new(
src: OuterViewPort<dyn TerminalView>
) -> (Arc<RwLock<Self>>, OuterViewPort<dyn TerminalView>) {
let port = ViewPort::new();
let v = Self::with_port(src, port.inner());
(v, port.into_outer())
}
pub fn with_port(
src_port: OuterViewPort<dyn TerminalView>,
dst_port: InnerViewPort<dyn TerminalView>
) -> Arc<RwLock<Self>> {
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<i16>| {
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<i16>;
type Value = TerminalAtom;
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
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<Vec<Point2<i16>>> {
self.src.area()
}
}

View file

@ -15,7 +15,6 @@ pub mod list;
pub mod tree_nav;
pub mod string_editor;
pub mod leveled_term_view;
pub mod bimap;

View file

@ -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<RwLock<usize>>,
}
impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItemEditor>
@ -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<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
{
pub fn get_seg_seq_view(&self) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
@ -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

View file

@ -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<i16>;
type Msg = IndexArea<Point2<i16>>;
}
impl IndexView<Point2<i16>> for VerticalSexprDecorator {
type Item = OuterViewPort<dyn TerminalView>;
fn area(&self) -> Option<Vec<Point2<i16>>> {
let mut area = (0..self.items.len()?)
.map(|i| Point2::new(1 as i16, i as i16))
.collect::<Vec<_>>();
area.push(Point2::new(0, 0));
area.push(Point2::new(2, self.items.len()? as i16 - 1));
Some(area)
fn area(&self) -> IndexArea<Point2<i16>> {
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<i16>) -> Option<Self::Item> {
@ -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),

View file

@ -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<Key: Hash + Eq + Clone + Send + Sync + std::fmt::Debug + 'static, Item: 'static>(
pub fn new_index_arg<Key: Clone + Send + Sync + 'static, Item: 'static>(
&mut self,
arg_key: ArgKey,
port: OuterViewPort<dyn IndexView<Key, Item = Item>>,
notify: impl Fn(&mut P, &Key) + Send + Sync + 'static
notify: impl Fn(&mut P, &IndexArea<Key>) + Send + Sync + 'static
) -> Arc<RwLock<Option<Arc<dyn IndexView<Key, Item = Item>>>>> {
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<D>, ChannelReceiver<D>)
)
-> Arc<RwLock<ProjectionArg<P, V, D>>>
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<P, V, D> UpdateTask for ProjectionArg<P, V, D>
where P: Send + Sync + 'static,
V: View + ?Sized,
D: ChannelData<Item = V::Msg>,
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<P, V, D> UpdateTask for RwLock<ProjectionArg<P, V, D>>
where P: Send + Sync + 'static,
V: View + ?Sized,
D: ChannelData<Item = V::Msg>,
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<P, Key, Item, D> Observer<dyn IndexView<Key, Item = Item>> for ProjectionArg<P, dyn IndexView<Key, Item = Item>, D>
where P: Send + Sync + 'static,
Key: Clone + Send + Sync,
D: ChannelData<Item = Key>,
D: ChannelData<Item = IndexArea<Key>>,
D::IntoIter: Send + Sync
{
fn reset(&mut self, new_src: Option<Arc<dyn IndexView<Key, Item = Item>>>) {
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<Key>) {
self.tx.send(msg.clone());
}
}

View file

@ -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<Item: 'static> OuterViewPort<dyn SequenceView<Item = Item>> {
impl<SrcView> View for Sequence2Index<SrcView>
where SrcView: SequenceView + ?Sized + 'static {
type Msg = usize;
type Msg = IndexArea<usize>;
}
impl<SrcView> IndexView<usize> for Sequence2Index<SrcView>
@ -67,8 +67,16 @@ where SrcView: SequenceView + ?Sized + 'static {
self.src_view.get(key)
}
fn area(&self) -> Option<Vec<usize>> {
Some((0 .. self.src_view.len()?).collect())
fn area(&self) -> IndexArea<usize> {
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<Arc<SrcView>>) {
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 ]));
}
}

View file

@ -4,7 +4,7 @@ use {
crate::{
singleton::{SingletonView},
core::{
Observer, ObserverExt, ObserverBroadcast,
Observer, ObserverBroadcast,
View, ViewPort, OuterViewPort
}
}

View file

@ -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<SrcView> View for Singleton2Index<SrcView>
where SrcView: SingletonView + ?Sized
{
type Msg = ();
type Msg = IndexArea<()>;
}
impl<SrcView> IndexView<()> for Singleton2Index<SrcView>
@ -60,9 +60,10 @@ where SrcView: SingletonView + ?Sized
{
type Item = SrcView::Item;
fn area(&self) -> Option<Vec<()>> {
Some(vec![()])
fn area(&self) -> IndexArea<()> {
IndexArea::Full
}
fn get(&self, _msg: &()) -> Option<Self::Item> {
Some(self.src_view.as_ref().unwrap().get())
}
@ -75,11 +76,11 @@ where SrcView: SingletonView + ?Sized
{
fn reset(&mut self, view: Option<Arc<SrcView>>) {
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);
}
}

View file

@ -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}

View file

@ -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<i16>;
type Value = TerminalAtom;
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;
@ -74,21 +77,11 @@ impl ImplIndexView for TerminalCompositor {
atom
}
fn area(&self) -> Option<Vec<Point2<i16>>> {
let mut area = Some(Vec::new());
fn area(&self) -> IndexArea<Point2<i16>> {
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

View file

@ -27,6 +27,7 @@ use {
set_channel
}
},
index::{IndexArea},
grid::{GridWindowIterator}
},
super::{
@ -119,24 +120,40 @@ struct TermOutObserver {
writer: Arc<TermOutWriter>
}
impl Observer<dyn TerminalView> for TermOutObserver {
fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
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);
impl TermOutObserver {
fn send_area(&mut self, area: IndexArea<Point2<i16>>) {
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);
}
}
}
}
}
fn notify(&mut self, pos: &Point2<i16>) {
self.dirty_pos_tx.send(*pos);
impl Observer<dyn TerminalView> for TermOutObserver {
fn reset(&mut self, view: Option<Arc<dyn TerminalView>>) {
self.writer.reset();
if let Some(view) = view {
self.send_area(view.area());
}
}
fn notify(&mut self, area: &IndexArea<Point2<i16>>) {
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::<Vec<_>>();
/*
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))?;
}

View file

@ -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"]

View file

@ -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<dyn TerminalView> for AsciiBox {
fn reset(&mut self, new_content: Option<Arc<dyn TerminalView>>) {
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<i16>) {
self.cast.notify(&(pt + Vector2::new(1, 1)));
fn notify(&mut self, area: &IndexArea<Point2<i16>>) {
self.cast.notify(&area.map(|pt| pt + Vector2::new(1, 1)));
self.fit_content();
}
}
impl View for AsciiBox {
type Msg = Point2<i16>;
type Msg = IndexArea<Point2<i16>>;
}
impl IndexView<Point2<i16>> for AsciiBox {
@ -114,19 +119,19 @@ impl IndexView<Point2<i16>> 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<Vec<Point2<i16>>> {
Some(GridWindowIterator::from(
Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2)
).collect())
fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range(Point2::new(0, 0) ..= Point2::new(1,1)+self.extent)
}
}

View file

@ -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<Arc<dyn TerminalView>>,
extent: Vector2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
}
impl AsciiBox {
pub fn new(
extent: Vector2<i16>,
content_port: OuterViewPort<dyn TerminalView>,
output_port: InnerViewPort<dyn TerminalView>
) -> Arc<RwLock<Self>> {
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<i16>) {
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<dyn TerminalView> for AsciiBox {
fn reset(&mut self, new_content: Option<Arc<dyn TerminalView>>) {
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<i16>) {
self.cast.notify(&(pt + Vector2::new(1, 1)));
}
}
impl View for AsciiBox {
type Msg = Point2<i16>;
}
impl IndexView<Point2<i16>> for AsciiBox {
type Item = TerminalAtom;
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
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<Vec<Point2<i16>>> {
Some(GridWindowIterator::from(
Point2::new(0, 0) .. Point2::new(self.extent.x+2, self.extent.y+2)
).collect())
}
}

View file

@ -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<Point2<i16>>;
}
impl IndexView<Point2<i16>> for TestView {
type Item = TerminalAtom;
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
Some(TerminalAtom::from('.'))
}
fn area(&self) -> IndexArea<Point2<i16>> {
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);
}
);

View file

@ -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<dyn TerminalView>) -> Option<crate::pty::PTY> {