2022-06-19 23:13:21 +02:00
|
|
|
use {
|
2023-02-13 18:39:45 +01:00
|
|
|
r3vi::{
|
|
|
|
view::{
|
|
|
|
Observer, ObserverBroadcast, ObserverExt, OuterViewPort, View, ViewPort,
|
|
|
|
singleton::*,
|
|
|
|
sequence::*,
|
|
|
|
},
|
|
|
|
projection::projection_helper::*
|
|
|
|
},
|
2022-06-19 23:13:21 +02:00
|
|
|
crate::{
|
2023-02-13 18:39:45 +01:00
|
|
|
editors::list::{ListCursor, ListCursorMode},
|
2022-06-19 23:13:21 +02:00
|
|
|
terminal::{TerminalView, TerminalStyle, make_label},
|
2022-12-19 11:26:07 +01:00
|
|
|
tree::{NestedNode, TreeNav},
|
2023-01-02 18:49:32 +01:00
|
|
|
utils::color::{bg_style_from_depth, fg_style_from_depth},
|
2022-12-19 11:26:07 +01:00
|
|
|
PtySegment
|
2022-06-19 23:13:21 +02:00
|
|
|
},
|
|
|
|
std::sync::Arc,
|
|
|
|
std::sync::RwLock,
|
|
|
|
};
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
pub enum ListSegment {
|
2022-06-19 23:13:21 +02:00
|
|
|
InsertCursor,
|
|
|
|
Item {
|
2022-12-19 11:26:07 +01:00
|
|
|
editor: NestedNode,
|
2022-06-19 23:13:21 +02:00
|
|
|
depth: usize,
|
|
|
|
cur_dist: isize,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
impl PtySegment for ListSegment {
|
2022-06-19 23:13:21 +02:00
|
|
|
fn pty_view(&self) -> OuterViewPort<dyn TerminalView> {
|
|
|
|
match self {
|
|
|
|
ListSegment::InsertCursor => {
|
|
|
|
make_label("|")
|
|
|
|
.map_item(move |_pt, atom| {
|
2022-10-14 23:42:35 +02:00
|
|
|
atom.add_style_front(TerminalStyle::fg_color((150,80,230)))
|
|
|
|
.add_style_front(TerminalStyle::bold(true))
|
2022-06-19 23:13:21 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
ListSegment::Item{ editor, depth, cur_dist } => {
|
|
|
|
let e = editor.clone();
|
|
|
|
let d = *depth;
|
2022-10-14 23:42:35 +02:00
|
|
|
let cur_dist = *cur_dist;
|
2022-12-19 11:26:07 +01:00
|
|
|
editor.get_view().map_item(move |_pt, atom| {
|
|
|
|
let c = e.get_cursor();
|
2022-10-14 23:42:35 +02:00
|
|
|
let cur_depth = c.tree_addr.len();
|
|
|
|
let select =
|
2022-10-15 03:52:38 +02:00
|
|
|
if cur_dist == 0 {
|
|
|
|
cur_depth
|
2022-10-14 23:42:35 +02:00
|
|
|
} else {
|
2022-10-15 03:52:38 +02:00
|
|
|
usize::MAX
|
2022-10-14 23:42:35 +02:00
|
|
|
};
|
|
|
|
atom
|
2022-10-15 03:52:38 +02:00
|
|
|
.add_style_back(bg_style_from_depth(select))
|
|
|
|
.add_style_back(TerminalStyle::bold(select==1))
|
2022-08-12 18:57:40 +02:00
|
|
|
.add_style_back(fg_style_from_depth(d))
|
2022-06-19 23:13:21 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
pub struct ListSegmentSequence {
|
2022-12-19 11:26:07 +01:00
|
|
|
data: Arc<dyn SequenceView<Item = NestedNode>>,
|
2022-06-19 23:13:21 +02:00
|
|
|
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
|
|
|
|
|
|
|
depth: usize,
|
|
|
|
cur_cursor: ListCursor,
|
|
|
|
|
2022-12-19 11:26:07 +01:00
|
|
|
port: ViewPort<dyn SequenceView<Item = ListSegment>>,
|
|
|
|
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListSegment>>>>,
|
2022-06-19 23:13:21 +02:00
|
|
|
proj_helper: ProjectionHelper<usize, Self>,
|
|
|
|
}
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
impl View for ListSegmentSequence {
|
2022-06-19 23:13:21 +02:00
|
|
|
type Msg = usize;
|
|
|
|
}
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
impl SequenceView for ListSegmentSequence {
|
2022-12-19 11:26:07 +01:00
|
|
|
type Item = ListSegment;
|
2022-06-19 23:13:21 +02:00
|
|
|
|
|
|
|
fn len(&self) -> Option<usize> {
|
|
|
|
match self.cur_cursor.mode {
|
|
|
|
ListCursorMode::Insert => {
|
|
|
|
Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 })
|
|
|
|
}
|
|
|
|
_ => self.data.len(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
|
|
|
let c = self.cursor.get();
|
2022-12-18 01:39:01 +01:00
|
|
|
Some(if let Some(cur) = c.idx {
|
2022-06-19 23:13:21 +02:00
|
|
|
match c.mode {
|
|
|
|
ListCursorMode::Select => {
|
|
|
|
ListSegment::Item {
|
|
|
|
editor: self.data.get(idx)?,
|
|
|
|
depth: self.depth,
|
|
|
|
cur_dist: cur - *idx as isize
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListCursorMode::Insert => {
|
|
|
|
if *idx < cur as usize {
|
|
|
|
ListSegment::Item {
|
|
|
|
editor: self.data.get(idx)?,
|
|
|
|
depth: self.depth,
|
|
|
|
cur_dist: cur - *idx as isize
|
|
|
|
}
|
|
|
|
} else if *idx == cur as usize {
|
|
|
|
ListSegment::InsertCursor
|
|
|
|
} else {
|
|
|
|
ListSegment::Item {
|
|
|
|
editor: self.data.get(&(*idx - 1))?,
|
|
|
|
depth: self.depth,
|
2022-10-14 23:42:35 +02:00
|
|
|
cur_dist: cur - *idx as isize
|
2022-06-19 23:13:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ListSegment::Item {
|
|
|
|
editor: self.data.get(&idx)?,
|
|
|
|
depth: self.depth,
|
|
|
|
cur_dist: *idx as isize + 1
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-02 18:49:32 +01:00
|
|
|
impl ListSegmentSequence {
|
2022-06-19 23:13:21 +02:00
|
|
|
pub fn new(
|
|
|
|
cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
|
2022-12-19 11:26:07 +01:00
|
|
|
data_port: OuterViewPort<dyn SequenceView<Item = NestedNode>>,
|
2022-06-19 23:13:21 +02:00
|
|
|
depth: usize
|
|
|
|
) -> Arc<RwLock<Self>> {
|
2022-12-19 11:26:07 +01:00
|
|
|
let out_port = ViewPort::new();
|
|
|
|
let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone());
|
2022-06-19 23:13:21 +02:00
|
|
|
let proj = Arc::new(RwLock::new(ListSegmentSequence {
|
|
|
|
cur_cursor: cursor_port.get_view().get(),
|
2022-12-19 11:26:07 +01:00
|
|
|
port: out_port.clone(),
|
2022-06-19 23:13:21 +02:00
|
|
|
depth,
|
2022-06-24 15:54:05 +02:00
|
|
|
|
2022-06-19 23:13:21 +02:00
|
|
|
cursor: proj_helper.new_singleton_arg(0, cursor_port, |s: &mut Self, _msg| {
|
|
|
|
let _old_cursor = s.cur_cursor;
|
|
|
|
s.cur_cursor = s.cursor.get();
|
|
|
|
|
|
|
|
// todo: optimize
|
|
|
|
s.cast.notify_each(0..=s.data.len().unwrap_or(0) + 1);
|
|
|
|
}),
|
|
|
|
|
|
|
|
data: proj_helper.new_sequence_arg(1, data_port, |s: &mut Self, idx| {
|
2022-12-18 01:39:01 +01:00
|
|
|
if let Some(cur_idx) = s.cur_cursor.idx {
|
2022-06-19 23:13:21 +02:00
|
|
|
match s.cur_cursor.mode {
|
|
|
|
ListCursorMode::Insert => {
|
|
|
|
if *idx < cur_idx as usize {
|
|
|
|
s.cast.notify(idx);
|
|
|
|
} else {
|
|
|
|
s.cast.notify(&(*idx + 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
s.cast.notify(idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
s.cast.notify(idx);
|
|
|
|
}
|
|
|
|
}),
|
2022-12-19 11:26:07 +01:00
|
|
|
cast: out_port.inner().get_broadcast(),
|
2022-06-19 23:13:21 +02:00
|
|
|
proj_helper,
|
|
|
|
}));
|
|
|
|
|
|
|
|
proj.write().unwrap().proj_helper.set_proj(&proj);
|
2022-12-19 11:26:07 +01:00
|
|
|
out_port.inner().set_view(Some(proj.clone()));
|
2022-06-19 23:13:21 +02:00
|
|
|
|
|
|
|
proj
|
|
|
|
}
|
2022-12-19 11:26:07 +01:00
|
|
|
|
|
|
|
pub fn get_view(&self) -> OuterViewPort<dyn SequenceView<Item = ListSegment>> {
|
|
|
|
self.port.outer()
|
|
|
|
}
|
2022-06-19 23:13:21 +02:00
|
|
|
}
|