index view: replace range() with area()
This commit is contained in:
parent
f3fa8a7af1
commit
6fe50416b5
6 changed files with 78 additions and 88 deletions
|
@ -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>) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +43,8 @@ impl<Key, V: IndexView<Key>> IndexView<Key> for Arc<V> {
|
||||||
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue