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![] } } } */