use { std::{sync::{Arc, RwLock}, any::Any}, cgmath::{Vector2, Point2}, r3vi::{ view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*}, buffer::{singleton::*} }, crate::{ type_system::{ReprTree, Context, TypeTerm}, terminal::{TerminalView, TerminalEvent, TerminalEditor, TerminalEditorResult, TerminalAtom}, diagnostics::{Diagnostics, Message}, tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp}, editors::list::{ListCursorMode}, commander::ObjCommander, } }; /* TODO: refactoring proposal struct NestedNodeDisplay { /// display view pub view: Option< OuterViewPort<dyn TerminalView> >, /// diagnostics pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >, /// depth pub depth: SingletonBuffer< usize >, } struct NestedNodeEdit { /// abstract editor pub editor: SingletonBuffer< Option< Arc<dyn Any + Send + Sync> > >, pub input_buf:: VecBuffer< NestedNode >, pub output_buf: VecBuffer< NestedNode >, /// commander & navigation pub cmd: SingletonBuffer< Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> > >, pub close_char: SingletonBuffer< Option< char > >, // could be replaced by cmd when TreeNav -CmdObjects are used pub tree_nav: SingletonBuffer< Option< Arc<RwLock<dyn TreeNav + Send + Sync>> > >, } pub struct NewNestedNode { /// context pub ctx: Arc<RwLock<Context>>, /// abstract data view pub data: Arc<RwLock<ReprTree>>, /// viewports for terminal display pub disp: NestedNodeDisplay, /// editor & commander objects pub edit: NestedNodeEdit } */ #[derive(Clone)] pub struct NestedNode { /// context pub ctx: Arc<RwLock<Context>>, /// abstract data view pub data: Arc<RwLock<ReprTree>>, /// display view pub view: Option< OuterViewPort<dyn TerminalView> >, /// diagnostics pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >, /// depth pub depth: OuterViewPort< dyn SingletonView<Item = usize> >, /// abstract editor pub editor: SingletonBuffer< Option< Arc<dyn Any + Send + Sync> > >, pub spillbuf: Arc<RwLock<Vec<Arc<RwLock<NestedNode>>>>>, /// commander & navigation pub cmd: SingletonBuffer< Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> > >, pub close_char: SingletonBuffer< Option< char > >, pub tree_nav: SingletonBuffer< Option< Arc<RwLock<dyn TreeNav + Send + Sync>> > >, } impl NestedNode { pub fn new(ctx: Arc<RwLock<Context>>, data: Arc<RwLock<ReprTree>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self { NestedNode { ctx, data, view: None, diag: None, depth, editor: SingletonBuffer::new(None), spillbuf: Arc::new(RwLock::new(Vec::new())), cmd: SingletonBuffer::new(None), close_char: SingletonBuffer::new(None), tree_nav: SingletonBuffer::new(None) } } /* TODO: move into separate file/module */ pub fn from_char(ctx: Arc<RwLock<Context>>, c: char) -> NestedNode { let buf = r3vi::buffer::singleton::SingletonBuffer::<char>::new(c); NestedNode::new( ctx.clone(), ReprTree::new_leaf( (&ctx, "( Char )"), buf.get_port().into() ), SingletonBuffer::new(0).get_port() ) .set_view(buf.get_port() .map(|c| TerminalAtom::from(c)) .to_index() .map_key( |_x| { Point2::new(0, 0) }, |p| { if *p == Point2::new(0,0) { Some(()) } else { None } }) ) .set_editor(Arc::new(RwLock::new(buf))) } //\\//\\ pub fn morph(self, ty: TypeTerm) -> NestedNode { Context::morph_node(self, ty) } pub fn get_type(&self) -> TypeTerm { self.data.read().unwrap().get_type().clone() } //\\//\\ pub fn set_editor(mut self, editor: Arc<dyn Any + Send + Sync>) -> Self { self.editor.set(Some(editor)); self } pub fn set_view(mut self, view: OuterViewPort<dyn TerminalView>) -> Self { self.view = Some(view); self } pub fn set_cmd(mut self, cmd: Arc<RwLock<dyn ObjCommander + Send + Sync>>) -> Self { self.cmd.set(Some(cmd)); self } pub fn set_nav(mut self, nav: Arc<RwLock<dyn TreeNav + Send + Sync>>) -> Self { self.tree_nav.set(Some(nav)); self } pub fn set_diag(mut self, diag: OuterViewPort<dyn SequenceView<Item = Message>>) -> Self { self.diag = Some(diag); self } //\\//\\ pub fn get_diag(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> { self.diag.clone().unwrap_or(ViewPort::new().into_outer()) } pub fn get_view(&self) -> OuterViewPort<dyn TerminalView> { self.view.clone().unwrap_or(ViewPort::new().into_outer()) } pub fn get_data_port<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<V>> where V::Msg: Clone { let ctx = self.ctx.clone(); let type_ladder = type_str.map(|s| ((&ctx, s)).into()); let repr_tree = ReprTree::descend_ladder(&self.data, type_ladder)?; repr_tree.clone().read().unwrap() .get_port::<V>().clone() } pub fn get_data_view<'a, V: View + ?Sized + 'static>(&'a self, type_str: impl Iterator<Item = &'a str>) -> Option<Arc<V>> where V::Msg: Clone { self.get_data_port::<V>(type_str)?.get_view() } /* TODO pub fn get_seq_view<'a, T: Clone>(&self, type_str: impl Iterator<Item = &'a str>) -> Option<OuterViewPort<dyn SingletonView<Item = T>>> { self.get_data_view::<dyn SequenceView<Item = NestedNode>>(type_str) .unwrap() .map({ move |node| { node.get_data_view::<dyn SingletonView<Item = T>>().get() } }) } */ pub fn get_edit<T: Send + Sync + 'static>(&self) -> Option<Arc<RwLock<T>>> { if let Some(edit) = self.editor.get() { if let Ok(edit) = edit.downcast::<RwLock<T>>() { Some(edit) } else { None } } else { None } } } /* impl TreeType for NestedNode { fn get_type(&self, addr: &TreeAddr) -> TypeLadder { if let Some(editor) = self.editor { editor.read().unwrap().get_type(addr) } else { vec![] } } } */ /* TODO: remove that at some point */ impl TerminalEditor for NestedNode { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { self.get_view() } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { let buf = SingletonBuffer::new(event.clone()); if let Some(cmd) = self.cmd.get() { cmd.write().unwrap().send_cmd_obj( ReprTree::new_leaf( self.ctx.read().unwrap().type_term_from_str("( TerminalEvent )").unwrap(), AnyOuterViewPort::from(buf.get_port()) )); } TerminalEditorResult::Continue } } impl TreeNav for NestedNode { fn get_cursor(&self) -> TreeCursor { if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_cursor() } else { TreeCursor::default() } } fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> { if let Some(tn) = self.tree_nav.get() { 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.get() { tn.read().unwrap().get_mode_view() } else { OuterViewPort::default() } } fn get_cursor_warp(&self) -> TreeCursor { if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_cursor_warp() } else { TreeCursor::default() } } fn get_height(&self, op: &TreeHeightOp) -> usize { if let Some(tn) = self.tree_nav.get() { tn.read().unwrap().get_height( op ) } else { 0 } } fn goby(&mut self, direction: Vector2<isize>) -> TreeNavResult { if let Some(tn) = self.tree_nav.get() { tn.write().unwrap().goby(direction) } else { TreeNavResult::Exit } } fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult { if let Some(tn) = self.tree_nav.get() { tn.write().unwrap().goto(new_cursor) } else { TreeNavResult::Exit } } } impl ObjCommander for NestedNode { fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult { if let Some(cmd) = self.cmd.get() { // todo: filter out tree-nav cmds and send them to tree_nav cmd.write().unwrap().send_cmd_obj(cmd_obj) } else { TreeNavResult::Exit } } } impl Diagnostics for NestedNode { fn get_msg_port(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> { self.get_diag() } }