index view: replace range() with area()

This commit is contained in:
Michael Sippel 2021-01-16 13:57:06 +01:00
parent f3fa8a7af1
commit 6fe50416b5
Signed by: senvas
GPG key ID: F96CF119C34B64A6
6 changed files with 78 additions and 88 deletions

View file

@ -1,7 +1,7 @@
use { use {
std::{ std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
ops::Range boxed::Box
}, },
cgmath::{Point2, Vector2}, cgmath::{Point2, Vector2},
crate::{ crate::{
@ -40,16 +40,12 @@ where V::Item: Default {
} }
pub fn set_offset(&mut self, new_offset: Vector2<i16>) { pub fn set_offset(&mut self, new_offset: Vector2<i16>) {
let old_range = self.range(); let old_area = self.area();
self.offset = new_offset; self.offset = new_offset;
let new_range = self.range(); let new_area = self.area();
if let Some(old_range) = old_range { if let Some(area) = old_area { self.cast.notify_each(area); }
self.cast.notify_each(GridWindowIterator::from(old_range)); if let Some(area) = new_area { self.cast.notify_each(area); }
}
if let Some(new_range) = new_range {
self.cast.notify_each(GridWindowIterator::from(new_range));
}
} }
} }
@ -69,25 +65,25 @@ where V::Item: Default {
} }
} }
fn range(&self) -> Option<Range<Point2<i16>>> { fn area(&self) -> Option<Vec<Point2<i16>>> {
let src_range = self.src.as_ref()?.range()?; Some(
Some((src_range.start + self.offset) .. (src_range.end + self.offset)) self.src.as_ref()?
.area()?.into_iter()
.map(|pos| pos + self.offset)
.collect()
)
} }
} }
impl<V: GridView + ?Sized> Observer<V> for GridOffset<V> impl<V: GridView + ?Sized> Observer<V> for GridOffset<V>
where V::Item: Default { where V::Item: Default {
fn reset(&mut self, view: Option<Arc<V>>) { fn reset(&mut self, view: Option<Arc<V>>) {
let old_range = self.range(); let old_area = self.area();
self.src = view; self.src = view;
let new_range = self.range(); let new_area = self.area();
if let Some(old_range) = old_range { if let Some(area) = old_area { self.cast.notify_each(area); }
self.cast.notify_each(GridWindowIterator::from(old_range)); if let Some(area) = new_area { self.cast.notify_each(area); }
}
if let Some(new_range) = new_range {
self.cast.notify_each(GridWindowIterator::from(new_range));
}
} }
fn notify(&self, msg: &Point2<i16>) { fn notify(&self, msg: &Point2<i16>) {

View file

@ -1,12 +1,13 @@
pub use { pub use {
std::{ std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
ops::Range boxed::Box
}, },
crate::{ crate::{
core::{ core::{
View, View,
Observer, Observer,
ObserverExt,
ObserverBroadcast, ObserverBroadcast,
ViewPort, ViewPort,
InnerViewPort, InnerViewPort,
@ -85,21 +86,27 @@ where DstItem: Default,
} }
} }
fn range(&self) -> Option<Range<Key>> { fn area(&self) -> Option<Vec<Key>> {
self.src_view.as_ref()?.range() self.src_view.as_ref()?.area()
} }
} }
impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F> impl<Key, DstItem, SrcView, F> Observer<SrcView> for MapIndexItem<Key, DstItem, SrcView, F>
where SrcView: IndexView<Key> + ?Sized, where DstItem: Default,
SrcView: IndexView<Key> + ?Sized,
F: Fn(&SrcView::Item) -> DstItem + Send + Sync F: Fn(&SrcView::Item) -> DstItem + Send + Sync
{ {
fn reset(&mut self, view: Option<Arc<SrcView>>) { fn reset(&mut self, view: Option<Arc<SrcView>>) {
// todo: notify on reset ?? let old_area = self.area();
self.src_view = view; 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); }
} }
fn notify(&self, msg: &Key) { fn notify(&self, msg: &Key) {
self.cast.notify(msg); self.cast.notify(msg);
} }
} }

View file

@ -1,10 +1,11 @@
pub mod map_item; pub mod map_item;
pub mod map_key;
use { use {
std::{ std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
ops::{Deref, Range} ops::Deref,
}, },
crate::core::View crate::core::View
}; };
@ -16,7 +17,7 @@ pub trait IndexView<Key> : View<Msg = Key> {
fn get(&self, key: &Key) -> Self::Item; fn get(&self, key: &Key) -> Self::Item;
fn range(&self) -> Option<Range<Key>> { fn area(&self) -> Option<Vec<Key>> {
None None
} }
} }
@ -30,8 +31,8 @@ impl<Key, V: IndexView<Key>> IndexView<Key> for RwLock<V> {
self.read().unwrap().get(key) self.read().unwrap().get(key)
} }
fn range(&self) -> Option<Range<Key>> { fn area(&self) -> Option<Vec<Key>> {
self.read().unwrap().range() self.read().unwrap().area()
} }
} }
@ -41,9 +42,9 @@ impl<Key, V: IndexView<Key>> IndexView<Key> for Arc<V> {
fn get(&self, key: &Key) -> Self::Item { fn get(&self, key: &Key) -> Self::Item {
self.deref().get(key) self.deref().get(key)
} }
fn range(&self) -> Option<Range<Key>> { fn area(&self) -> Option<Vec<Key>> {
self.deref().range() self.deref().area()
} }
} }
@ -54,7 +55,7 @@ pub trait ImplIndexView : Send + Sync {
type Value; type Value;
fn get(&self, key: &Self::Key) -> Self::Value; fn get(&self, key: &Self::Key) -> Self::Value;
fn range(&self) -> Option<Range<Self::Key>> { fn area(&self) -> Option<Vec<Self::Key>> {
None None
} }
} }
@ -70,7 +71,8 @@ impl<V: ImplIndexView> IndexView<V::Key> for V {
(self as &V).get(key) (self as &V).get(key)
} }
fn range(&self) -> Option<Range<V::Key>> { fn area(&self) -> Option<Vec<V::Key>> {
(self as &V).range() (self as &V).area()
} }
} }

View file

@ -1,6 +1,7 @@
use { use {
std::{ std::{
ops::Range, boxed::Box,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}, },
cgmath::Point2, cgmath::Point2,
@ -16,7 +17,7 @@ use {
}, },
sequence::SequenceView, sequence::SequenceView,
index::{ImplIndexView}, index::{ImplIndexView},
grid::{GridView}, grid::{GridView, GridWindowIterator},
terminal::{TerminalAtom, TerminalStyle, TerminalView}, terminal::{TerminalAtom, TerminalStyle, TerminalView},
//vec_buffer::VecBuffer //vec_buffer::VecBuffer
} }
@ -37,19 +38,19 @@ impl ImplIndexView for StringEditorState {
let data = self.data.read().unwrap(); let data = self.data.read().unwrap();
if pos.y == 0 { if pos.y == 0 {
if pos.x < data.len() as i16 + 3 { let i = pos.x as usize;
let i = pos.x as usize; if i < data.len() + 3 {
return Some( return Some(
if i == 0 { if i == 0 {
TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130))) TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130)))
} else if i-1 == self.cursor { } else if i-1 == self.cursor {
TerminalAtom::new('|', TerminalStyle::fg_color((180,200,130)).add(TerminalStyle::bold(true))) TerminalAtom::new('|', TerminalStyle::fg_color((180,200,130)).add(TerminalStyle::bold(false)))
} else if i-1 == data.len()+1 { } else if i-1 == data.len()+1 {
TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130))) TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130)))
} else { } else {
TerminalAtom::new( TerminalAtom::new(
data.get(i as usize - if i <= self.cursor { 1 } else { 2 }).unwrap().clone(), data.get(i as usize - if i <= self.cursor { 1 } else { 2 }).unwrap().clone(),
TerminalStyle::fg_color((80,150,80)) TerminalStyle::fg_color((80,150,80)).add(TerminalStyle::bold(true))
) )
} }
) )
@ -59,11 +60,10 @@ impl ImplIndexView for StringEditorState {
None None
} }
fn range(&self) -> Option<Range<Point2<i16>>> { fn area(&self) -> Option<Vec<Point2<i16>>> {
Some( Some(GridWindowIterator::from(
Point2::new(0, 0) Point2::new(0, 0)
.. Point2::new(self.data.read().unwrap().len() as i16 + 3, 1) .. Point2::new(self.data.read().unwrap().len() as i16 + 3, 1)).collect())
)
} }
} }

View file

@ -2,7 +2,7 @@ use {
std::{ std::{
sync::{Arc, Weak, RwLock}, sync::{Arc, Weak, RwLock},
collections::HashMap, collections::HashMap,
ops::Range, boxed::Box,
cmp::{min, max} cmp::{min, max}
}, },
cgmath::Point2, cgmath::Point2,
@ -29,14 +29,14 @@ impl Observer<dyn TerminalView> for CompositeLayer {
c.layers.get_mut(&self.idx).unwrap().1 = view.clone(); c.layers.get_mut(&self.idx).unwrap().1 = view.clone();
if let Some(old_view) = old_view { if let Some(old_view) = old_view {
if let Some(range) = old_view.range() { if let Some(area) = old_view.area() {
c.cast.notify_each(GridWindowIterator::from(range)); c.cast.notify_each(area);
} }
} }
if let Some(view) = view.as_ref() { if let Some(view) = view.as_ref() {
if let Some(range) = view.range() { if let Some(area) = view.area() {
c.cast.notify_each(GridWindowIterator::from(range)); c.cast.notify_each(area);
} }
} }
} }
@ -55,42 +55,27 @@ impl Observer<dyn TerminalView> for CompositeLayer {
pub struct TerminalCompositeView { pub struct TerminalCompositeView {
idx_count: usize, idx_count: usize,
layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>, layers: HashMap<usize, (Arc<RwLock<CompositeLayer>>, Option<Arc<dyn TerminalView>>)>,
range: Option<Range<Point2<i16>>>, area: Option<Vec<Point2<i16>>>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>> cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
} }
impl TerminalCompositeView { impl TerminalCompositeView {
fn update_range(&mut self) { fn update_range(&mut self) {
if self.layers.len() == 0 { self.area = Some(Vec::new());
self.range = Some(Point2::new(0, 0) .. Point2::new(0, 0))
} else {
self.range = None;
for (idx, layer) in self.layers.iter() { for (idx, layer) in self.layers.iter() {
self.range = if let Some(view) = layer.1.as_ref() {
if let ( if let (
Some(new_range), Some(mut new_area),
Some(old_range) Some(mut area)
) = ( ) = (
if let Some(view) = layer.1.as_ref() { view.area(),
view.range().clone() self.area.as_mut()
} else { ) {
None area.append(&mut new_area);
}, } else {
self.range.as_ref() self.area = None;
) { }
Some(
Point2::new(
min(old_range.start.x, new_range.start.x),
min(old_range.start.y, new_range.start.y)
) .. Point2::new(
max(old_range.end.x, new_range.end.x),
max(old_range.end.y, new_range.end.y)
)
)
} else {
None
};
} }
} }
} }
@ -106,6 +91,7 @@ impl ImplIndexView for TerminalCompositeView {
for idx in 0 .. self.idx_count { for idx in 0 .. self.idx_count {
if let Some(l) = self.layers.get(&idx) { if let Some(l) = self.layers.get(&idx) {
if let Some(view) = l.1.as_ref() { if let Some(view) = l.1.as_ref() {
/*
if let Some(range) = view.range() { if let Some(range) = view.range() {
if pos.x < range.start.x || if pos.x < range.start.x ||
pos.x >= range.end.x || pos.x >= range.end.x ||
@ -114,7 +100,7 @@ impl ImplIndexView for TerminalCompositeView {
continue; continue;
} }
} }
*/
match (atom, view.get(pos)) { match (atom, view.get(pos)) {
(None, next) => atom = next, (None, next) => atom = next,
(Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)), (Some(last), Some(next)) => atom = Some(next.add_style_back(last.style)),
@ -127,8 +113,8 @@ impl ImplIndexView for TerminalCompositeView {
atom atom
} }
fn range(&self) -> Option<Range<Point2<i16>>> { fn area(&self) -> Option<Vec<Point2<i16>>> {
self.range.clone() self.area.clone()
} }
} }
@ -145,7 +131,7 @@ impl TerminalCompositor {
TerminalCompositeView { TerminalCompositeView {
idx_count: 0, idx_count: 0,
layers: HashMap::new(), layers: HashMap::new(),
range: Some(Point2::new(0, 0) .. Point2::new(0, 0)), area: Some(Vec::new()),
cast: port.get_broadcast() cast: port.get_broadcast()
} }
)); ));

View file

@ -125,10 +125,9 @@ impl Observer<dyn TerminalView> for TermOutObserver {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
if let Some(view) = view { if let Some(view) = view {
for pos in GridWindowIterator::from( for pos in view.area().unwrap_or(
view.range().unwrap_or( GridWindowIterator::from(
Point2::new(0, 0) .. Point2::new(w as i16, h as i16) Point2::new(0, 0) .. Point2::new(w as i16, h as i16)).collect()
)
) { ) {
self.dirty_pos_tx.send(pos); self.dirty_pos_tx.send(pos);
} }