lib-nested/lib-nested-core/src/editors/list/segment.rs

139 lines
4.2 KiB
Rust
Raw Normal View History

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},
2024-01-07 20:04:23 +01:00
edit_tree::{EditTree}
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 {
2024-01-07 20:04:23 +01:00
editor: EditTree,
2022-06-19 23:13:21 +02:00
cur_dist: isize,
}
}
2023-01-02 18:49:32 +01:00
pub struct ListSegmentSequence {
2024-01-07 20:04:23 +01:00
data: Arc<dyn SequenceView<Item = EditTree>>,
2022-06-19 23:13:21 +02:00
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
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)?,
cur_dist: cur - *idx as isize
}
}
ListCursorMode::Insert => {
if *idx < cur as usize {
ListSegment::Item {
editor: self.data.get(idx)?,
cur_dist: cur - *idx as isize
}
} else if *idx == cur as usize {
ListSegment::InsertCursor
} else {
ListSegment::Item {
editor: self.data.get(&(*idx - 1))?,
cur_dist: cur - *idx as isize
2022-06-19 23:13:21 +02:00
}
}
}
}
} else {
ListSegment::Item {
editor: self.data.get(&idx)?,
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>>,
2024-01-07 20:04:23 +01:00
data_port: OuterViewPort<dyn SequenceView<Item = EditTree>>,
2022-06-19 23:13:21 +02:00
) -> 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-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
}