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

330 lines
10 KiB
Rust
Raw Normal View History

2023-02-13 18:39:45 +01:00
use {
r3vi::{
view::{OuterViewPort, singleton::*, sequence::*},
buffer::{singleton::*, vec::*}
2023-02-13 18:39:45 +01:00
},
crate::{
type_system::{Context, TypeTerm, ReprTree},
editors::list::{ListCursor, ListCursorMode},
2023-02-13 18:39:45 +01:00
tree::{NestedNode, TreeNav}
},
std::sync::{Arc, RwLock}
2023-02-13 18:39:45 +01:00
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct ListEditor {
pub(super) cursor: SingletonBuffer<ListCursor>,
2023-02-24 18:44:01 +01:00
pub data: VecBuffer<NestedNode>,
2023-02-13 18:39:45 +01:00
pub(super) addr_port: OuterViewPort<dyn SequenceView<Item = isize>>,
pub(super) mode_port: OuterViewPort<dyn SingletonView<Item = ListCursorMode>>,
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::<NestedNode>::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 {
data.get(idx as usize).get_mode_view()
} 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).get_addr_view();
}
}
}
OuterViewPort::default()
}
})
.to_sequence()
.flatten()
])
.get_port()
.to_sequence()
.flatten(),
cursor,
data,
ctx,
typ,
}
}
pub fn into_node(self, depth: usize) -> NestedNode {
let data = self.get_data();
let ctx = self.ctx.clone();
let editor = Arc::new(RwLock::new(self));
NestedNode::new(depth)
.set_ctx(ctx)
.set_data(data)
.set_editor(editor.clone())
.set_nav(editor.clone())
// .set_cmd(editor.clone())
}
pub fn new_node(
node: NestedNode,
item_type: TypeTerm
) -> NestedNode {
let ctx = node.ctx.clone().unwrap();
let editor = ListEditor::new(
ctx.clone(),
item_type,
);
let data = editor.get_data();
let editor = Arc::new(RwLock::new(editor));
node.set_data(data)
.set_editor(editor.clone())
.set_nav(editor.clone())
}
2023-02-13 18:39:45 +01:00
pub fn get_item_type(&self) -> TypeTerm {
self.typ.clone()
}
pub fn get_seq_type(&self) -> TypeTerm {
TypeTerm::Type {
2023-02-17 00:59:07 +01:00
id: self.ctx.read().unwrap().get_typeid("List").unwrap(),
args: vec![ self.get_item_type().into() ]
}
2023-02-13 18:39:45 +01:00
}
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()
}
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))
} else {
None
}
} else {
None
}
}
pub fn get_item_mut(&mut self) -> Option<MutableVecAccess<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
}
}
pub fn is_listlist(&self) -> bool {
self.ctx.read().unwrap().is_list_type(&self.typ)
/*
match self.typ.clone() {
TypeTerm::Type { id, args } => {
id == self.ctx.read().unwrap().get_typeid("List").unwrap()
},
TypeTerm::Num(_) => false
}
*/
}
/// delete all items
pub fn clear(&mut self) {
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: NestedNode) {
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 {
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);
}
}
2023-02-13 18:39:45 +01:00
/// split the list off at the current cursor position and return the second half
pub fn split(&mut self) -> ListEditor {
let mut le = ListEditor::new(self.ctx.clone(), self.typ.clone());
let cur = self.cursor.get();
if let Some(idx) = cur.idx {
let idx = idx as usize;
for _ in idx .. self.data.len() {
le.data.push( self.data.get(idx) );
self.data.remove(idx);
}
if self.is_listlist() {
if idx > 0 && idx < self.data.len()+1 {
let prev_idx = idx - 1; // we are in insert mode, last element before cursor
let prev_node = self.data.get(prev_idx);
if let Some(prev_editor) = prev_node.editor.clone() {
2023-02-24 19:26:46 +01:00
let prev_editor = prev_editor.downcast::<RwLock<ListEditor>>().unwrap();
let prev_editor = prev_editor.write().unwrap();
if prev_editor.get_data_port().get_view().unwrap().iter()
.filter_map(|x| x.get_data_view::<dyn SingletonView<Item = Option<char>>>(vec![].into_iter())?.get()).count() == 0
{
drop(prev_editor);
self.data.remove(prev_idx);
}
}
}
}
2023-02-13 18:39:45 +01:00
}
le
}
/// append data of other editor at the end and set cursor accordingly
pub fn join(&mut self, other: &ListEditor) {
let selfcur = self.cursor.get();
let othercur = other.cursor.get();
let is_bottom = self.get_cursor().tree_addr.len() == 1 ||
other.get_cursor().tree_addr.len() == 1;
let is_insert =
selfcur.mode == ListCursorMode::Insert
|| othercur.mode == ListCursorMode::Insert;
let is_primary = self.get_cursor().tree_addr.len() > 1;
self.cursor.set(ListCursor {
mode: if is_insert && is_bottom {
ListCursorMode::Insert
} else {
ListCursorMode::Select
},
idx: Some(self.data.len() as isize -
if is_primary {
1
} else {
0
}
)
});
for i in 0 .. other.data.len() {
self.data.push(other.data.get(i));
}
}
}
2023-02-17 00:59:07 +01:00
/*
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;
2023-02-13 18:39:45 +01:00
2023-02-17 00:59:07 +01:00
let mut addr = addr.clone();
if self.data.len() > 0 {
addr.0.remove(0);
self.data.get(idx).get_type(addr)
} else {
vec![]
}
}
}
*/