lib-nested/nested/src/editors/list/editor.rs

493 lines
16 KiB
Rust

use {
r3vi::{
view::{ViewPort, OuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*, vec::*}
},
crate::{
type_system::{Context, TypeTerm, ReprTree},
editors::list::{ListCursor, ListCursorMode, ListCmd},
tree::{NestedNode, TreeNav, TreeCursor},
diagnostics::Diagnostics,
commander::ObjCommander
},
std::sync::{Arc, RwLock}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ListEditor {
pub(super) cursor: SingletonBuffer<ListCursor>,
// todo: (?) remove RwLock<..> around NestedNode ??
pub data: VecBuffer< Arc<RwLock<NestedNode>> >,
pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>,
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
depth: OuterViewPort<dyn SingletonView<Item = usize>>,
pub(crate) ctx: Arc<RwLock<Context>>,
/// item type
pub(super) typ: TypeTerm,
}
impl ListEditor {
pub fn new(
ctx: Arc<RwLock<Context>>,
typ: TypeTerm,
) -> Self {
let cursor = SingletonBuffer::new(ListCursor::default());
let data : VecBuffer<Arc<RwLock<NestedNode>>> = VecBuffer::new();
ListEditor {
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 {
if idx >= 0 && idx < data.len() as isize {
data.get(idx as usize).read().unwrap().get_mode_view()
} else {
eprintln!("ListEditor::mode_port invalid cursor idx");
ip
}
} else {
ip
}
}
}
}
})
.flatten(),
addr_port: VecBuffer::<OuterViewPort<dyn SequenceView<Item = isize>>>::with_data(
vec![
cursor.get_port()
.to_sequence()
.filter_map(|cur| cur.idx),
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).read().unwrap().get_addr_view();
}
}
}
OuterViewPort::default()
}
})
.to_sequence()
.flatten()
])
.get_port()
.to_sequence()
.flatten(),
cursor,
data,
spillbuf: Arc::new(RwLock::new(Vec::new())),
ctx,
typ,
depth: SingletonBuffer::new(0).get_port()
}
}
pub fn into_node(mut self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> NestedNode {
let data = self.get_data();
let ctx = self.ctx.clone();
self.depth = depth.clone();
let editor = Arc::new(RwLock::new(self));
let e = editor.read().unwrap();
let mut node = NestedNode::new(ctx, data, depth)
.set_editor(editor.clone())
.set_nav(editor.clone())
.set_cmd(editor.clone())
.set_diag(e
.get_data_port()
.enumerate()
.map(
|(idx, item_editor)| {
let idx = *idx;
item_editor
.get_msg_port()
.map(
move |msg| {
let mut msg = msg.clone();
msg.addr.insert(0, idx);
msg
}
)
}
)
.flatten()
);
node.spillbuf = e.spillbuf.clone();
node
}
pub fn get_item_type(&self) -> TypeTerm {
self.typ.clone()
}
pub fn get_seq_type(&self) -> TypeTerm {
TypeTerm::App(vec![
TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("List").unwrap()),
self.get_item_type().into()
])
}
pub fn get_cursor_port(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursor>> {
self.cursor.get_port()
}
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = NestedNode>> {
self.data.get_port().to_sequence().map(
|x| x.read().unwrap().clone()
)
}
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
let data_view = self.get_data_port();
ReprTree::new_leaf(
self.get_seq_type(),
data_view.into()
)
}
pub fn get_item(&self) -> Option<NestedNode> {
if let Some(idx) = self.cursor.get().idx {
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
if idx < self.data.len() {
Some(self.data.get(idx).read().unwrap().clone())
} else {
None
}
} else {
None
}
}
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<Arc<RwLock<NestedNode>>>> {
if let Some(idx) = self.cursor.get().idx {
let idx = crate::utils::modulo(idx as isize, self.data.len() as isize) as usize;
if idx < self.data.len() {
Some(self.data.get_mut(idx))
} else {
None
}
} else {
None
}
}
/// is the element-type also a list-like editor (i.e. impls TreeNav)
pub fn is_listlist(&self) -> bool {
self.ctx.read().unwrap().is_list_type(&self.typ)
}
/// delete all items
pub fn clear(&mut self) {
let mut b = self.spillbuf.write().unwrap();
for i in 0..self.data.len() {
b.push( self.data.get(i) );
}
self.data.clear();
self.cursor.set(ListCursor::home());
}
/// delete item before the cursor
pub fn delete_pxev(&mut self) {
let mut cur = self.cursor.get();
if let Some(idx) = cur.idx {
if idx > 0 && idx <= self.data.len() as isize {
cur.idx = Some(idx as isize - 1);
self.cursor.set(cur);
self.data.remove(idx as usize - 1);
}
}
}
/// delete item after the cursor
pub fn delete_nexd(&mut self) {
if let Some(idx) = self.cursor.get().idx {
if idx < self.data.len() as isize {
self.data.remove(idx as usize);
}
}
}
/// insert a new element
pub fn insert(&mut self, item: Arc<RwLock<NestedNode>>) {
eprintln!("list insert");
item.read().unwrap().depth.0.set_view(
self.depth.map(|d| d+1).get_view()
);
let mut cur = self.cursor.get();
if let Some(idx) = cur.idx {
match cur.mode {
ListCursorMode::Insert => {
self.data.insert(idx as usize, item.clone());
if self.is_listlist() {
cur.mode = ListCursorMode::Select;
} else {
eprintln!("list insert: is not a listlist ({:?})", self.typ);
item.write().unwrap().goto(TreeCursor::none());
cur.idx = Some(idx + 1);
}
}
ListCursorMode::Select => {
self.data.insert(1 + idx as usize, item.clone());
if self.is_listlist() {
cur.idx = Some(idx + 1);
}
}
}
self.cursor.set(cur);
} else {
//eprintln!("insert: no cursor");
}
}
/// split the list off at the current cursor position and return the second half
pub fn split(&mut self) {
eprintln!("split");
let cur = self.cursor.get();
if let Some(idx) = cur.idx {
let idx = idx as usize;
for _ in idx .. self.data.len() {
self.spillbuf.write().unwrap().push(
self.data.get(idx)
);
self.data.remove(idx);
}
/* in case the split leaves an empty item-list
* as a last element, remove it
*/
/*
if self.is_listlist() {
if idx > 0 && idx < self.data.len()+1 {
/* we are in insert mode,
* get element before cursor
*/
let prev_idx = idx - 1;
let prev_node = self.data.get(prev_idx);
let prev_node = prev_node.read().unwrap();
if prev_node.get_data_view::<dyn SequenceView<Item = NestedNode>>(vec![].into_iter()).iter().count() == 0 {
drop(prev_node);
self.data.remove(prev_idx);
}
}
}
*/
}
}
pub fn listlist_split(&mut self) {
eprintln!("listlist split");
let cur = self.get_cursor();
if let Some(mut item) = self.get_item().clone() {
item.send_cmd_obj(ListCmd::Split.into_repr_tree(&self.ctx));
if cur.tree_addr.len() < 3 {
item.goto(TreeCursor::none());
self.set_leaf_mode(ListCursorMode::Insert);
self.nexd();
let mut b = item.spillbuf.write().unwrap();
let mut tail_node = Context::make_node(&self.ctx, self.typ.clone(), self.depth.map(|d| d+1)).unwrap();
tail_node.goto(TreeCursor::home());
for node in b.iter() {
eprintln!("splid :send to tail node");
tail_node
.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
SingletonBuffer::<NestedNode>::new(
node.read().unwrap().clone()
).get_port().into()
)
);
}
b.clear();
drop(b);
drop(item);
tail_node.goto(TreeCursor::home());
if cur.tree_addr.len() > 1 {
tail_node.dn();
}
self.insert(
Arc::new(RwLock::new(tail_node))
);
} else {
self.up();
self.listlist_split();
self.dn();
}
}
}
pub fn listlist_join_pxev(&mut self, idx: isize) {
{
let cur_editor = self.data.get(idx as usize);
let pxv_editor = self.data.get(idx as usize-1);
let mut cur_editor = cur_editor.write().unwrap();
let mut pxv_editor = pxv_editor.write().unwrap();
let oc0 = cur_editor.get_cursor();
// tell cur_editor move all its elements into its spill-buffer
cur_editor.goto(TreeCursor::none());
cur_editor.send_cmd_obj(
ListCmd::Clear.into_repr_tree( &self.ctx )
);
pxv_editor.goto(TreeCursor {
tree_addr: vec![-1],
leaf_mode: ListCursorMode::Insert
});
let old_cur = pxv_editor.get_cursor();
let data = cur_editor.spillbuf.read().unwrap();
for x in data.iter() {
pxv_editor.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
SingletonBuffer::<NestedNode>::new(
x.read().unwrap().clone()
).get_port().into()
)
);
}
// fixme: is it oc0 or old_cur ??
if oc0.tree_addr.len() > 1 {
pxv_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0], 0 ],
leaf_mode: ListCursorMode::Insert
});
pxv_editor.send_cmd_obj(ListCmd::DeletePxev.into_repr_tree( &self.ctx ));
} else if oc0.tree_addr.len() > 0 {
pxv_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0] ],
leaf_mode: ListCursorMode::Insert
});
}
}
self.cursor.set(ListCursor {
idx: Some(idx as isize - 1),
mode: ListCursorMode::Select
});
// remove cur_editor from top list, its elements are now in pxv_editor
self.data.remove(idx as usize);
}
pub fn listlist_join_nexd(&mut self, idx: usize) {
{
let cur_editor = self.data.get(idx);
let nxd_editor = self.data.get(idx + 1);
let mut cur_editor = cur_editor.write().unwrap();
let mut nxd_editor = nxd_editor.write().unwrap();
let oc0 = cur_editor.get_cursor();
// tell next_editor move all its elements into its spill-buffer
nxd_editor.goto(TreeCursor::none());
nxd_editor.send_cmd_obj(
ListCmd::Clear.into_repr_tree( &self.ctx )
);
let old_cur = cur_editor.get_cursor();
cur_editor.goto(TreeCursor {
tree_addr: vec![-1],
leaf_mode: ListCursorMode::Insert
});
let data = nxd_editor.spillbuf.read().unwrap();
for x in data.iter() {
cur_editor.send_cmd_obj(
ReprTree::new_leaf(
(&self.ctx, "( NestedNode )"),
SingletonBuffer::<NestedNode>::new(
x.read().unwrap().clone()
).get_port().into()
)
);
}
// fixme: is it oc0 or old_cur ??
if oc0.tree_addr.len() > 1 {
cur_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0], -1 ],
leaf_mode: ListCursorMode::Insert
});
cur_editor.send_cmd_obj(ListCmd::DeleteNexd.into_repr_tree( &self.ctx ));
} else if oc0.tree_addr.len() > 0 {
cur_editor.goto(TreeCursor {
tree_addr: vec![ old_cur.tree_addr[0] ],
leaf_mode: ListCursorMode::Insert
});
} else {
cur_editor.goto(TreeCursor::none());
}
}
// remove next_editor from top list, its elements are now in cur_editor
self.data.remove(idx+1);
}
}
/*
use crate::{
type_system::TypeLadder,
tree::{TreeType, TreeAddr}
};
impl TreeType for ListEditor {
fn get_type(&self, addr: &TreeAddr) -> TypeLadder {
let idx = crate::utils::modulo::modulo(addr.0[0] as isize, self.data.len() as isize) as usize;
let mut addr = addr.clone();
if self.data.len() > 0 {
addr.0.remove(0);
self.data.get(idx).get_type(addr)
} else {
vec![]
}
}
}
*/