move list editor module to nested crate
This commit is contained in:
parent
2d17254b2c
commit
07ee04bba4
6 changed files with 963 additions and 347 deletions
nested/src/list
283
nested/src/list/sexpr.rs
Normal file
283
nested/src/list/sexpr.rs
Normal file
|
@ -0,0 +1,283 @@
|
|||
use {
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
pub struct ListDecorator {
|
||||
opening_port: OuterViewPort<dyn TerminalView>,
|
||||
closing_port: OuterViewPort<dyn TerminalView>,
|
||||
delim_port: OuterViewPort<dyn TerminalView>,
|
||||
items: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||
|
||||
list_style: TerminalStyle,
|
||||
item_style: TerminalStyle,
|
||||
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>>>,
|
||||
proj_helper: ProjectionHelper<Self>
|
||||
}
|
||||
|
||||
impl View for ListDecorator {
|
||||
type Msg = usize;
|
||||
}
|
||||
|
||||
impl SequenceView for ListDecorator {
|
||||
type Item = OuterViewPort<dyn TerminalView>;
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
let l = self.items.len()?;
|
||||
Some(if l == 0 { 2 } else { 2*l + 2 })
|
||||
}
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
||||
let item_idx = idx / 2;
|
||||
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))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ListDecorator {
|
||||
pub fn new(
|
||||
opening: &str,
|
||||
closing: &str,
|
||||
delim: &str,
|
||||
level: usize,
|
||||
items_port: OuterViewPort<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)
|
||||
}
|
||||
),
|
||||
cast: out_port.get_broadcast(),
|
||||
proj_helper
|
||||
}));
|
||||
|
||||
li.write().unwrap().proj_helper.set_proj(&li);
|
||||
|
||||
out_port.set_view(Some(li.clone()));
|
||||
li
|
||||
}
|
||||
}
|
||||
|
||||
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
|
||||
|
||||
use crate::{index::IndexView, grid::GridView};
|
||||
|
||||
pub struct VerticalSexprDecorator {
|
||||
opening_port: OuterViewPort<dyn TerminalView>,
|
||||
closing_port: OuterViewPort<dyn TerminalView>,
|
||||
items: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||
|
||||
list_style: TerminalStyle,
|
||||
item_style: TerminalStyle,
|
||||
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn GridView<Item = OuterViewPort<dyn TerminalView>>>>>,
|
||||
proj_helper: ProjectionHelper<Self>
|
||||
}
|
||||
|
||||
impl View for VerticalSexprDecorator {
|
||||
type Msg = 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 get(&self, pt: &Point2<i16>) -> Option<Self::Item> {
|
||||
let item_idx = pt.y as usize;
|
||||
let list_style = self.list_style.clone();
|
||||
let item_style = self.item_style.clone();
|
||||
let l = self.items.len().unwrap_or(0);
|
||||
|
||||
match pt.x {
|
||||
0 => {
|
||||
if pt.y == 0 {
|
||||
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)))
|
||||
} 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)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VerticalSexprDecorator {
|
||||
pub fn new(
|
||||
opening: &str,
|
||||
closing: &str,
|
||||
level: usize,
|
||||
items_port: OuterViewPort<dyn SequenceView<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)
|
||||
}
|
||||
),
|
||||
cast: out_port.get_broadcast(),
|
||||
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>;
|
||||
fn vertical_sexpr_view(&self, level: usize) -> OuterViewPort<dyn TerminalView>;
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
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()
|
||||
);
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue