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

View file

@ -32,7 +32,7 @@ use {
}, },
string_editor::StringEditor, string_editor::StringEditor,
leveled_term_view::LeveledTermView, leveled_term_view::LeveledTermView,
list::SExprView list::{SExprView, ListDecoration}
} }
}; };
@ -59,7 +59,7 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<SubEditor>>>>, data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<SubEditor>>>>,
make_item_editor: FnMakeItemEditor, make_item_editor: FnMakeItemEditor,
level: usize, level: usize,
pub segment_seq: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>, segment_seq: OuterViewPort<dyn SequenceView<Item = ListEditorViewSegment>>,
} }
impl<SubEditor, FnMakeItemEditor> TerminalEditor for ListEditor<SubEditor, FnMakeItemEditor> impl<SubEditor, FnMakeItemEditor> TerminalEditor for ListEditor<SubEditor, FnMakeItemEditor>
@ -67,7 +67,7 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>> FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
{ {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
self.segment_seq.horizontal_sexpr_view(0) self.horizontal_sexpr_view()
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
@ -369,6 +369,49 @@ impl<SubEditor, FnMakeItemEditor> ListEditor<SubEditor, FnMakeItemEditor>
where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static, where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>> FnMakeItemEditor: Fn() -> Arc<RwLock<SubEditor>>
{ {
pub fn get_seg_seq_view(&self) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
self.segment_seq
.map(
|segment| match segment {
ListEditorViewSegment::InsertCursor =>
make_label("|")
.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::fg_color((90,60,200)))
.add_style_back(TerminalStyle::bold(true))
),
ListEditorViewSegment::Select(sub_view) =>
sub_view.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::bg_color((90,60,200)))
),
ListEditorViewSegment::Edit(sub_view) =>
sub_view.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::bg_color((0,0,0)))
.add_style_back(TerminalStyle::bold(true))
),
ListEditorViewSegment::View(sub_view) =>
sub_view.clone()
}
)
}
pub fn horizontal_sexpr_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view().horizontal_sexpr_view(0)
}
pub fn vertical_sexpr_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view().vertical_sexpr_view(0)
}
pub fn path_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view()
.decorate("<", ">", "/", 1)
.to_grid_horizontal()
.flatten()
}
pub fn new(make_item_editor: FnMakeItemEditor) -> Self { pub fn new(make_item_editor: FnMakeItemEditor) -> Self {
let cursor_port = ViewPort::new(); let cursor_port = ViewPort::new();
let data_port = ViewPort::new(); let data_port = ViewPort::new();
@ -391,32 +434,7 @@ where SubEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
cursor, cursor,
make_item_editor, make_item_editor,
level: 0, level: 0,
segment_seq: segment_view_port segment_seq: segment_view_port.outer()
.outer()
.map(
|segment| match segment {
ListEditorViewSegment::InsertCursor =>
make_label("|")
.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::fg_color((90,60,200)))
.add_style_back(TerminalStyle::bold(true))
),
ListEditorViewSegment::Select(sub_view) =>
sub_view.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::bg_color((90,60,200)))
),
ListEditorViewSegment::Edit(sub_view) =>
sub_view.map_item(
|_pt, atom|
atom.add_style_back(TerminalStyle::bg_color((0,0,0)))
.add_style_back(TerminalStyle::bold(true))
),
ListEditorViewSegment::View(sub_view) =>
sub_view.clone()
}
)
} }
} }

View file

@ -3,5 +3,5 @@ pub mod editor;
pub mod sexpr; pub mod sexpr;
pub use editor::ListEditor; pub use editor::ListEditor;
pub use sexpr::SExprView; pub use sexpr::{SExprView, ListDecoration};

View file

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

View file

@ -294,95 +294,9 @@ write::
} }
/*
// list views
{
let items_port = ViewPort::new();
let items = VecBuffer::with_data(
vec![
arg1_hex_unic_port.clone()
.map(|c| TerminalAtom::from(c))
.to_index()
.map_key(
|idx| Point2::new(*idx as i16, 0 as i16),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
),
ed.insert_view()
.map_item(
|_pos, atom|
TerminalAtom::new(
atom.c.unwrap_or(' '),
TerminalStyle::fg_color(
if let Some(c) = atom.c {
if c == '|' {
(200, 200, 90)
} else if c.is_digit(10) {
(0, 200, 0)
} else {
(255, 0, 0)
}
} else {
(0, 0, 0)
}
).add(
TerminalStyle::bg_color((0,0,0))
)
)
),
arg1_hex_unic_port.clone()
.map(|c| TerminalAtom::from(c))
.to_index()
.map_key(
|idx| Point2::new(*idx as i16, 0 as i16),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
),
],
items_port.inner()
);
let par_items_port = ViewPort::new();
let par_items = VecBuffer::with_data(
vec![
items_port.outer().to_sequence().sexpr_view(1),
arg1_hex_unic_port.clone()
.map(|c| TerminalAtom::from(c))
.to_index()
.map_key(
|idx| Point2::new(*idx as i16, 0 as i16),
|pt| if pt.y == 0 { Some(pt.x as usize) } else { None }
),
],
par_items_port.inner()
);
compositor.write().unwrap().push(
par_items_port.outer()
.to_sequence()
.sexpr_view(0)
.offset(Vector2::new(45, 5))
);
}
for c in _arg1_vec {
ed.insert(c);
}
*/
let cur_size_port = ViewPort::new(); let cur_size_port = ViewPort::new();
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner()); let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10), cur_size_port.inner());
// compositor.write().unwrap()
// .push(
let label_port = cur_size_port.outer()
.map(
|size| make_label(format!("Current Size: {:?}", size).as_str())
);
// );
//term_port.update();
//eprintln!("start loop:");
{ {
// let history_port = ViewPort::new(); // let history_port = ViewPort::new();
// let mut history = VecBuffer::new(history_port.inner()); // let mut history = VecBuffer::new(history_port.inner());
@ -411,11 +325,12 @@ write::
let mut te = ListEditor::new(make_sub_editor.clone()); let mut te = ListEditor::new(make_sub_editor.clone());
compositor.write().unwrap().push( compositor.write().unwrap().push(
te.segment_seq.horizontal_sexpr_view(0).offset(cgmath::Vector2::new(40,y)) te.path_view()
.offset(cgmath::Vector2::new(40,y))
); );
y += 1; y += 1;
let mut p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port()); let mut p = te.get_data_port().map(|string_editor| string_editor.read().unwrap().get_data_port());
loop { loop {
term_port.update(); term_port.update();
@ -494,7 +409,9 @@ write::
compositor.write().unwrap().push(magic.offset(Vector2::new(40, y))); compositor.write().unwrap().push(magic.offset(Vector2::new(40, y)));
y += 1; y += 1;
compositor.write().unwrap().push( compositor.write().unwrap().push(
te.segment_seq.horizontal_sexpr_view(0).offset(cgmath::Vector2::new(40,y)) te
.horizontal_sexpr_view()
.offset(Vector2::new(40, y))
); );
y += 1; y += 1;