implement tree cursor widget as projection pipeline
This commit is contained in:
parent
a9550600f4
commit
47b8900adc
9 changed files with 191 additions and 89 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue