list editor: add path view

add decorate() on OuterViewPort to create a ListDecorator
This commit is contained in:
Michael Sippel 2021-08-15 02:05:33 +02:00
parent 78c5ffcdbe
commit 127c43bca0
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 165 additions and 246 deletions
nested/src/list

View file

@ -1,20 +1,13 @@
use {
crate::{
core::{InnerViewPort, Observer, ObserverBroadcast, OuterViewPort, View, ViewPort},
projection::ProjectionHelper,
sequence::SequenceView,
terminal::{make_label, TerminalStyle, TerminalView},
},
cgmath::Point2,
std::sync::Arc,
std::sync::RwLock,
cgmath::{Point2},
crate::{
core::{
View,
ViewPort,
OuterViewPort,
InnerViewPort,
Observer,
ObserverBroadcast
},
sequence::{SequenceView},
terminal::{TerminalStyle, TerminalView, make_label},
projection::ProjectionHelper
}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -29,7 +22,7 @@ pub struct ListDecorator {
item_style: TerminalStyle,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>>>,
proj_helper: ProjectionHelper<Self>
proj_helper: ProjectionHelper<Self>,
}
impl View for ListDecorator {
@ -41,7 +34,7 @@ impl SequenceView for ListDecorator {
fn len(&self) -> Option<usize> {
let l = self.items.len()?;
Some(if l == 0 { 2 } else { 2*l + 2 })
Some(if l == 0 { 2 } else { 2 * l + 2 })
}
fn get(&self, idx: &usize) -> Option<Self::Item> {
@ -49,22 +42,23 @@ impl SequenceView for ListDecorator {
let list_style = self.list_style.clone();
let item_style = self.item_style.clone();
let l = self.items.len().unwrap_or(0);
Some(
if *idx == 0 {
self.opening_port.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else if (l == 0 && *idx == 1) || *idx == 2*l {
self.closing_port.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else if idx % 2 == 0 {
self.delim_port.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else {
self.items
.get(&item_idx)?
.map_item(move |_, atom| atom.add_style_back(item_style))
}
)
Some(if *idx == 0 {
self.opening_port
.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else if (l == 0 && *idx == 1) || *idx == 2 * l {
self.closing_port
.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else if idx % 2 == 0 {
self.delim_port
.clone()
.map_item(move |_, atom| atom.add_style_back(list_style))
} else {
self.items
.get(&item_idx)?
.map_item(move |_, atom| atom.add_style_back(item_style))
})
}
}
@ -75,51 +69,64 @@ impl ListDecorator {
delim: &str,
level: usize,
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>
out_port: InnerViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let li = Arc::new(RwLock::new(ListDecorator {
opening_port: make_label(opening),
closing_port: make_label(closing),
delim_port: make_label(delim),
items: proj_helper.new_sequence_arg(
items_port,
|s: &mut Self, item_idx| {
s.cast.notify(
&(*item_idx * 2 + 1)
);
s.cast.notify(
&(*item_idx * 2 + 2)
);
}
),
list_style: TerminalStyle::fg_color(
match level {
0 => (200, 120, 10),
1 => (120, 200, 10),
_ => (255, 255, 255)
}
),
item_style: TerminalStyle::fg_color(
match level {
_ => (255, 255, 255)
}
),
items: proj_helper.new_sequence_arg(items_port, |s: &mut Self, item_idx| {
s.cast.notify(&(*item_idx * 2 + 1));
s.cast.notify(&(*item_idx * 2 + 2));
}),
list_style: TerminalStyle::fg_color(match level {
0 => (200, 120, 10),
1 => (120, 200, 10),
_ => (255, 255, 255),
}),
item_style: TerminalStyle::fg_color(match level {
_ => (255, 255, 255),
}),
cast: out_port.get_broadcast(),
proj_helper
proj_helper,
}));
li.write().unwrap().proj_helper.set_proj(&li);
out_port.set_view(Some(li.clone()));
li
}
}
pub trait ListDecoration {
fn decorate(
&self,
opening: &str,
closing: &str,
delim: &str,
level: usize,
) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>;
}
impl ListDecoration for OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
fn decorate(
&self,
opening: &str,
closing: &str,
delim: &str,
level: usize,
) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
let port = ViewPort::new();
ListDecorator::new(opening, closing, delim, level, self.clone(), port.inner());
port.into_outer()
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
use crate::{index::IndexView, grid::GridView};
use crate::{grid::GridView, index::IndexView};
pub struct VerticalSexprDecorator {
opening_port: OuterViewPort<dyn TerminalView>,
@ -130,7 +137,7 @@ pub struct VerticalSexprDecorator {
item_style: TerminalStyle,
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>>>,
proj_helper: ProjectionHelper<Self>
proj_helper: ProjectionHelper<Self>,
}
impl View for VerticalSexprDecorator {
@ -141,7 +148,9 @@ 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<_>>();
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)
@ -156,28 +165,38 @@ impl IndexView<Point2<i16>> for VerticalSexprDecorator {
match pt.x {
0 => {
if pt.y == 0 {
Some(self.opening_port.clone()
.map_item(move |_, atom| atom.add_style_back(list_style)))
Some(
self.opening_port
.clone()
.map_item(move |_, atom| atom.add_style_back(list_style)),
)
} else {
None
}
}
1 => {
if item_idx < l {
Some(self.items.get(&item_idx)?.map_item(move |_, atom| atom.add_style_back(item_style)))
Some(
self.items
.get(&item_idx)?
.map_item(move |_, atom| atom.add_style_back(item_style)),
)
} else {
None
}
}
2 => {
if (l == 0 && pt.y == 0) || (item_idx+1 == l) {
Some(self.closing_port.clone()
.map_item(move |_, atom| atom.add_style_back(list_style)))
if (l == 0 && pt.y == 0) || (item_idx + 1 == l) {
Some(
self.closing_port
.clone()
.map_item(move |_, atom| atom.add_style_back(list_style)),
)
} else {
None
}
}
_ => None
_ => None,
}
}
}
@ -188,51 +207,37 @@ impl VerticalSexprDecorator {
closing: &str,
level: usize,
items_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
out_port: InnerViewPort<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>
out_port: InnerViewPort<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>,
) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let li = Arc::new(RwLock::new(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)
);
}
),
list_style: TerminalStyle::fg_color(
match level {
0 => (200, 120, 10),
1 => (120, 200, 10),
_ => (255, 255, 255)
}
),
item_style: TerminalStyle::fg_color(
match level {
_ => (255, 255, 255)
}
),
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));
}),
list_style: TerminalStyle::fg_color(match level {
0 => (200, 120, 10),
1 => (120, 200, 10),
_ => (255, 255, 255),
}),
item_style: TerminalStyle::fg_color(match level {
_ => (255, 255, 255),
}),
cast: out_port.get_broadcast(),
proj_helper
proj_helper,
}));
li.write().unwrap().proj_helper.set_proj(&li);
out_port.set_view(Some(li.clone()));
li
}
}
pub trait SExprView {
fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
fn vertical_bar_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
@ -242,42 +247,21 @@ pub trait SExprView {
impl SExprView for OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
fn horizontal_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
let port = ViewPort::new();
ListDecorator::new(
"(", ")", " ",
level,
self.clone(),
port.inner()
);
ListDecorator::new("(", ")", " ", level, self.clone(), port.inner());
port.into_outer()
.to_grid_horizontal()
.flatten()
port.into_outer().to_grid_horizontal().flatten()
}
fn vertical_bar_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
let port = ViewPort::new();
ListDecorator::new(
"Λ", "V", "|",
level,
self.clone(),
port.inner()
);
ListDecorator::new("Λ", "V", "|", level, self.clone(), port.inner());
port.into_outer()
.to_grid_vertical()
.flatten()
port.into_outer().to_grid_vertical().flatten()
}
fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView> {
let port = ViewPort::new();
VerticalSexprDecorator::new(
"(", ")",
level,
self.clone(),
port.inner()
);
port.into_outer()
.flatten()
VerticalSexprDecorator::new("(", ")", level, self.clone(), port.inner());
port.into_outer().flatten()
}
}