lib-nested/lib-nested-core/src/edit_tree/node.rs

225 lines
6.4 KiB
Rust

use {
std::{sync::{Arc, RwLock}, any::Any},
cgmath::{Vector2, Point2},
r3vi::{
view::{View, ViewPort, OuterViewPort, AnyOuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*, vec::*}
},
laddertypes::{TypeTerm},
crate::{
repr_tree::{ReprTree, ReprTreeArc, Context},
edit_tree::{TreeNav, TreeCursor, TreeNavResult, TreeHeightOp, diagnostics::{Diagnostics, Message}},
editors::{list::{ListCursorMode}, ObjCommander}
}
};
#[derive(Clone)]
pub struct EdittreeDisplay {
/// display view
pub view: Arc<RwLock<ReprTree>>,
/// diagnostics
pub diag: Option< OuterViewPort<dyn SequenceView<Item = Message>> >,
/// depth
pub depth: OuterViewPort<dyn SingletonView<Item = usize>>,
}
#[derive(Clone)]
pub struct EdittreeControl {
/// abstract editor
pub editor: SingletonBuffer<
Option< Arc<dyn Any + Send + Sync> >
>,
pub spillbuf: Arc<RwLock< Vec< ReprTreeArc > >>,
/// commander & navigation
pub cmd: SingletonBuffer<
Option< Arc<RwLock<dyn ObjCommander + Send + Sync>> >
>, /// abstract data view
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>> >
>,
}
#[derive(Clone)]
pub struct EditTree {
/// context
pub ctx: Arc<RwLock<Context>>,
/// viewports for terminal display
pub disp: EdittreeDisplay,
/// editor & commander objects
pub ctrl: EdittreeControl
}
impl EditTree {
pub fn new(ctx: Arc<RwLock<Context>>, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> Self {
EditTree {
disp: EdittreeDisplay {
view: ReprTree::new_arc(Context::parse(&ctx, "Display")),
diag: None,
depth,
},
ctrl: EdittreeControl {
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),
},
ctx
}
}
pub fn set_editor(mut self, editor: Arc<dyn Any + Send + Sync>) -> Self {
self.ctrl.editor.set(Some(editor));
self
}
pub fn set_cmd(mut self, cmd: Arc<RwLock<dyn ObjCommander + Send + Sync>>) -> Self {
self.ctrl.cmd.set(Some(cmd));
self
}
pub fn set_nav(mut self, nav: Arc<RwLock<dyn TreeNav + Send + Sync>>) -> Self {
self.ctrl.tree_nav.set(Some(nav));
self
}
pub fn set_diag(mut self, diag: OuterViewPort<dyn SequenceView<Item = Message>>) -> Self {
self.disp.diag = Some(diag);
self
}
//\\//\\
pub fn get_diag(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
self.disp.diag.clone().unwrap_or(ViewPort::new().into_outer())
}
pub fn get_edit<T: Send + Sync + 'static>(&self) -> Option<Arc<RwLock<T>>> {
if let Some(edit) = self.ctrl.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![]
}
}
}
*/
impl TreeNav for EditTree {
fn get_cursor(&self) -> TreeCursor {
if let Some(tn) = self.ctrl.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.ctrl.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.ctrl.tree_nav.get() {
tn.read().unwrap().get_mode_view()
} else {
OuterViewPort::default()
}
}
fn get_cursor_warp(&self) -> TreeCursor {
if let Some(tn) = self.ctrl.tree_nav.get() {
tn.read().unwrap().get_cursor_warp()
} else {
TreeCursor::default()
}
}
fn get_height(&self, op: &TreeHeightOp) -> usize {
if let Some(tn) = self.ctrl.tree_nav.get() {
tn.read().unwrap().get_height( op )
} else {
0
}
}
fn goby(&mut self, direction: Vector2<isize>) -> TreeNavResult {
if let Some(tn) = self.ctrl.tree_nav.get() {
tn.write().unwrap().goby(direction)
} else {
TreeNavResult::Exit
}
}
fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult {
if let Some(tn) = self.ctrl.tree_nav.get() {
tn.write().unwrap().goto(new_cursor)
} else {
TreeNavResult::Exit
}
}
}
use crate::edit_tree::nav::TreeNavCmd;
impl ObjCommander for EditTree {
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
if cmd_obj.read().unwrap().get_type() == &Context::parse(&self.ctx, "TreeNavCmd") {
if let Some(cmd) = cmd_obj.read().unwrap().get_view::<dyn SingletonView<Item = TreeNavCmd>>() {
match cmd.get() {
TreeNavCmd::pxev => self.pxev(),
TreeNavCmd::nexd => self.nexd(),
TreeNavCmd::qpxev => self.qpxev(),
TreeNavCmd::qnexd => self.qnexd(),
TreeNavCmd::up => self.up(),
TreeNavCmd::dn => self.dn(),
_ => TreeNavResult::Continue
}
} else {
TreeNavResult::Exit
}
} else if let Some(cmd) = self.ctrl.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 EditTree {
fn get_msg_port(&self) -> OuterViewPort<dyn SequenceView<Item = Message>> {
self.get_diag()
}
}