implement tree cursor widget as projection pipeline

This commit is contained in:
Michael Sippel 2023-01-07 04:37:44 +01:00
parent a9550600f4
commit 47b8900adc
Signed by: senvas
GPG key ID: F96CF119C34B64A6
9 changed files with 191 additions and 89 deletions

View file

@ -4,6 +4,12 @@ pub enum ListCursorMode {
Select
}
impl Default for ListCursorMode {
fn default() -> Self {
ListCursorMode::Select
}
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct ListCursor {
pub mode: ListCursorMode,

View file

@ -6,11 +6,12 @@ use {
ListCursor,
ListSegment,
ListSegmentSequence,
ListCursorMode
},
sequence::{SequenceView},
singleton::{SingletonBuffer, SingletonView},
terminal::{TerminalView},
tree::NestedNode,
tree::{NestedNode, TreeNav},
vec::{VecBuffer, MutableVecAccess},
PtySegment
},
@ -23,6 +24,9 @@ pub struct ListEditor {
pub(super) cursor: SingletonBuffer<ListCursor>,
pub(crate) data: VecBuffer<NestedNode>,
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
pub(crate) ctx: Arc<RwLock<Context>>,
pub(super) typ: TypeTerm,
pub(super) depth: usize,
@ -35,9 +39,67 @@ impl ListEditor {
typ: TypeTerm,
depth: usize
) -> Self {
let mut cursor = SingletonBuffer::new(ListCursor::default());
let mut data = VecBuffer::<NestedNode>::new();
ListEditor {
cursor: SingletonBuffer::new(ListCursor::default()),
data: VecBuffer::<NestedNode>::new(),
mode_port: cursor
.get_port()
.map({
let data = data.clone();
move |c| {
let ip = SingletonBuffer::new(c.mode).get_port();
match c.mode {
ListCursorMode::Insert => ip,
ListCursorMode::Select => {
if let Some(idx) = c.idx {
data.get(idx as usize).get_mode_view()
} else {
ip
}
}
}
}
})
.flatten(),
addr_port: VecBuffer::<OuterViewPort<dyn SequenceView<Item = isize>>>::with_data(
vec![
cursor.get_port()
.map(
|x| {
// todo implement this with filter_map
let mut b = VecBuffer::new();
if let Some(i) = x.idx {
b.push(i);
}
b.get_port().to_sequence()
}
)
.to_sequence()
.flatten(),
cursor.get_port()
.map({
let data = data.clone();
move |cur| {
if cur.mode == ListCursorMode::Select {
if let Some(idx) = cur.idx {
if idx >= 0 && idx < data.len() as isize {
return data.get(idx as usize).get_addr_view();
}
}
}
OuterViewPort::default()
}
})
.to_sequence()
.flatten()
])
.get_port()
.to_sequence()
.flatten(),
cursor,
data,
ctx,
typ,
depth,
@ -77,6 +139,7 @@ impl ListEditor {
None
}
}
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<NestedNode>> {
if let Some(idx) = self.cursor.get().idx {
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;

View file

@ -1,10 +1,13 @@
use {
crate::{
core::{OuterViewPort},
sequence::{SequenceView},
list::{
ListCursor, ListCursorMode,
ListEditor
},
tree::{TreeCursor, TreeNav, TreeNavResult},
singleton::SingletonView,
Nested
},
cgmath::Vector2
@ -13,6 +16,14 @@ use {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl TreeNav for ListEditor {
fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> {
self.addr_port.clone()
}
fn get_mode_view(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursorMode>> {
self.mode_port.clone()
}
fn get_cursor_warp(&self) -> TreeCursor {
let cur = self.cursor.get();
match cur.mode {

View file

@ -52,11 +52,11 @@ where
type Item = SrcView::Item;
fn get(&self, _idx: &usize) -> Option<Self::Item> {
Some(self.src_view.as_ref().unwrap().get())
Some(self.src_view.as_ref()?.get())
}
fn len(&self) -> Option<usize> {
Some(1)
Some(if self.src_view.is_some() { 1 } else { 0 })
}
}

View file

@ -40,11 +40,9 @@ use {
};
pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
let label_port = ViewPort::new();
let _label = VecBuffer::with_data(s.chars().collect(), label_port.inner());
let label = VecBuffer::with_data(s.chars().collect());
let v = label_port
.outer()
let v = label.get_port()
.to_sequence()
.map(|c| TerminalAtom::from(c))
.to_index()
@ -55,3 +53,21 @@ pub fn make_label(s: &str) -> OuterViewPort<dyn TerminalView> {
v
}
impl OuterViewPort<dyn TerminalView> {
pub fn with_style(&self, style: TerminalStyle) -> OuterViewPort<dyn TerminalView> {
self.map_item(
move |_idx, a|
a.add_style_front(style)
)
}
pub fn with_fg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView> {
self.with_style(TerminalStyle::fg_color(col))
}
pub fn with_bg_color(&self, col: (u8, u8, u8)) -> OuterViewPort<dyn TerminalView> {
self.with_style(TerminalStyle::bg_color(col))
}
}

View file

@ -1,7 +1,15 @@
use {
crate::list::ListCursorMode,
crate::tree::TreeCursor,
cgmath::Vector2
crate::vec::VecBuffer,
crate::core::{OuterViewPort},
crate::sequence::{SequenceView, decorator::Separate},
crate::singleton::{SingletonBuffer, SingletonView},
cgmath::Vector2,
crate::{
terminal::{TerminalView, TerminalStyle, make_label}
}
};
#[derive(Clone, Copy, Eq, PartialEq)]
@ -21,6 +29,8 @@ impl From<TreeNavResult> for TerminalEditorResult {
}
*/
pub trait TreeNav {
/* CORE
*/
@ -28,6 +38,14 @@ pub trait TreeNav {
TreeCursor::default()
}
fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> {
VecBuffer::<isize>::new().get_port().to_sequence()
}
fn get_mode_view(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursorMode>> {
SingletonBuffer::new(ListCursorMode::Select).get_port()
}
fn get_cursor_warp(&self) -> TreeCursor {
TreeCursor::default()
}
@ -124,5 +142,35 @@ pub trait TreeNav {
}
}
}
fn get_cursor_widget(&self) -> OuterViewPort<dyn TerminalView> {
VecBuffer::with_data(
vec![
make_label("@").with_fg_color((150, 80,230)),
self.get_addr_view()
.map(|i|
make_label(&format!("{}", i)).with_fg_color((0, 100, 20)))
.separate(make_label(".").with_fg_color((150, 80,230)))
.to_grid_horizontal()
.flatten(),
make_label(":").with_fg_color((150, 80,230)),
self.get_mode_view()
.map(|mode| {
make_label(
match mode {
ListCursorMode::Insert => "INSERT",
ListCursorMode::Select => "SELECT"
})
.with_fg_color((200, 200, 20))
})
.to_grid()
.flatten(),
make_label(":").with_fg_color((150, 80,230))
]
).get_port()
.to_sequence()
.to_grid_horizontal()
.flatten()
}
}

View file

@ -4,12 +4,14 @@ use {
crate::{
core::{ViewPort, OuterViewPort, AnyOuterViewPort},
type_system::{ReprTree, Context},
singleton::{SingletonBuffer},
singleton::{SingletonBuffer, SingletonView},
sequence::SequenceView,
terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult},
diagnostics::{Diagnostics, Message},
tree::{TreeNav, TreeCursor, TreeNavResult},
list::{ListCursorMode},
commander::ObjCommander,
vec::VecBuffer,
Nested
}
};
@ -62,6 +64,22 @@ impl TreeNav for NestedNode {
}
}
fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> {
if let Some(tn) = self.tree_nav.as_ref() {
tn.read().unwrap().get_addr_view()
} else {
OuterViewPort::default()
}
}
fn get_mode_view(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursorMode>> {
if let Some(tn) = self.tree_nav.as_ref() {
tn.read().unwrap().get_mode_view()
} else {
OuterViewPort::default()
}
}
fn get_cursor_warp(&self) -> TreeCursor {
if let Some(tn) = self.tree_nav.as_ref() {
tn.read().unwrap().get_cursor_warp()

View file

@ -34,7 +34,7 @@ impl<T> VecBuffer<T>
where
T: Clone + Send + Sync + 'static,
{
pub fn with_data(data: Vec<T>, port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
pub fn with_data_port(data: Vec<T>, port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
let data = Arc::new(RwLock::new(data));
port.set_view(Some(data.clone()));
@ -48,8 +48,12 @@ where
}
}
pub fn with_data(data: Vec<T>) -> Self {
VecBuffer::with_data_port(data, ViewPort::new().into_inner())
}
pub fn with_port(port: InnerViewPort<RwLock<Vec<T>>>) -> Self {
VecBuffer::with_data(vec![], port)
VecBuffer::with_data_port(vec![], port)
}
pub fn new() -> Self {

View file

@ -13,6 +13,7 @@ use {
core::{port::UpdateTask, Observer, AnyOuterViewPort, ViewPort},
type_system::{Context, ReprTree},
index::IndexArea,
singleton::{SingletonView, SingletonBuffer},
list::{ListCursorMode, PTYListEditor},
sequence::{decorator::{SeqDecorStyle, Separate}},
terminal::{
@ -121,14 +122,10 @@ async fn main() {
});
let mut cur_size = nested::singleton::SingletonBuffer::new(Vector2::new(10, 10));
let mut status_chars = VecBuffer::new();
table.insert_iter(vec![
(Point2::new(0, 0), magic.clone()),
(
Point2::new(0, 1),
status_chars.get_port().to_sequence().to_grid_horizontal(),
),
(Point2::new(0, 1), process_list_editor.editor.read().unwrap().get_cursor_widget()),
(Point2::new(0, 2), magic.clone()),
(Point2::new(0, 3), make_label(" ")),
(Point2::new(0, 4),
@ -162,12 +159,7 @@ async fn main() {
)
.separate({
let mut buf = IndexBuffer::new();
buf.insert(Point2::new(1,0),
make_label(" ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~")
.map_item(
|p,a|
a.add_style_front(TerminalStyle::fg_color((40,40,40)))
)
buf.insert(Point2::new(1,0), make_label(" ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~").with_fg_color((40,40,40))
);
buf.get_port()
})
@ -183,17 +175,14 @@ async fn main() {
|entry| {
let mut b = VecBuffer::new();
b.push(
make_label("@")
.map_item(|_p,a| a
.add_style_back(TerminalStyle::bold(true))
.add_style_back(TerminalStyle::fg_color((120,120,0))))
make_label("@").with_style(
TerminalStyle::bold(true)
.add(TerminalStyle::fg_color((120,120,0))))
);
for x in entry.addr.iter() {
b.push(
make_label(&format!("{}", x))
.map_item(|_p,a| a
.add_style_back(TerminalStyle::fg_color((0, 100, 20))))
make_label(&format!("{}", x)).with_fg_color((0, 100, 20))
);
b.push(
make_label(".")
@ -222,12 +211,7 @@ async fn main() {
]);
let (_w, _h) = termion::terminal_size().unwrap();
/*
compositor
.write()
.unwrap()
.push(monstera::make_monstera().offset(Vector2::new(w as i16 - 38, 0)));
*/
compositor
.write()
.unwrap()
@ -307,54 +291,6 @@ async fn main() {
process_list_editor.send_cmd(&ev);
}
}
status_chars.clear();
let cur = process_list_editor.editor.read().unwrap().get_cursor();
if cur.tree_addr.len() > 0 {
status_chars.push(TerminalAtom::new(
'@',
TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)),
));
for x in cur.tree_addr {
for c in format!("{}", x).chars() {
status_chars
.push(TerminalAtom::new(c, TerminalStyle::fg_color((0, 100, 20))));
}
status_chars.push(TerminalAtom::new(
'.',
TerminalStyle::fg_color((150, 80,230))
));
}
status_chars.push(TerminalAtom::new(
':',
TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)),
));
for c in match cur.leaf_mode {
ListCursorMode::Insert => "INSERT",
ListCursorMode::Select => "SELECT"
}
.chars()
{
status_chars.push(TerminalAtom::new(
c,
TerminalStyle::fg_color((200, 200, 20)),
));
}
status_chars.push(TerminalAtom::new(
':',
TerminalStyle::fg_color((150, 80,230)).add(TerminalStyle::bold(true)),
));
} else {
for c in "Press <DN> to enter".chars() {
status_chars.push(TerminalAtom::new(
c,
TerminalStyle::fg_color((200, 200, 20)),
));
}
}
}
drop(term);