lib-nested/lib-nested-core/src/editors/list/nav.rs

426 lines
17 KiB
Rust

use {
r3vi::{
view::{
OuterViewPort,
singleton::*,
sequence::*
}
},
crate::{
editors::list::{
ListCursor, ListCursorMode,
editor::ListEditor
},
edit_tree::{TreeCursor, TreeNav, TreeNavResult, TreeHeightOp}
},
cgmath::Vector2
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
impl TreeNav for ListEditor {
fn get_addr_view(&self) -> OuterViewPort<dyn SequenceView<Item = isize>> {
self.addr_port.clone()
}
fn get_mode_view(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursorMode>> {
self.mode_port.clone()
}
fn get_height(&self, op: &TreeHeightOp) -> usize {
match op {
TreeHeightOp::P | TreeHeightOp::Q => {
if self.data.len() > 0 {
1 + self.data.get(match op {
TreeHeightOp::P => 0,
TreeHeightOp::Q => self.data.len() - 1,
_ => 0
}).read().unwrap().get_height(op)
} else {
1
}
}
TreeHeightOp::Max => {
1 + (0..self.data.len() as usize)
.map(|i| self.data
.get(i).read().unwrap()
.get_height(&TreeHeightOp::Max)
)
.max()
.unwrap_or(0)
}
}
}
fn get_cursor_warp(&self) -> TreeCursor {
let cur = self.cursor.get();
match cur.mode {
ListCursorMode::Insert => TreeCursor {
leaf_mode: cur.mode,
tree_addr: if let Some(i) = cur.idx {
vec![
i - self.data.len() as isize - 1
]
} else {
vec![]
}
},
ListCursorMode::Select => {
if let Some(i) = cur.idx {
if i < self.data.len() as isize {
let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor_warp();
sub_cur.tree_addr.insert(0, i as isize - self.data.len() as isize);
return sub_cur;
} else {
return TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![ i as isize - self.data.len() as isize ],
};
}
}
TreeCursor {
leaf_mode: cur.mode,
tree_addr: vec![],
}
}
}
}
fn get_cursor(&self) -> TreeCursor {
let cur = self.cursor.get();
match cur.mode {
ListCursorMode::Insert => TreeCursor {
leaf_mode: cur.mode,
tree_addr: if let Some(i) = cur.idx {
vec![i]
} else {
vec![]
},
},
ListCursorMode::Select => {
if let Some(i) = cur.idx {
if i < self.data.len() as isize {
let mut sub_cur = self.data.get(i as usize).read().unwrap().get_cursor();
if sub_cur.tree_addr.len() > 0 {
sub_cur.tree_addr.insert(0, i as isize);
return sub_cur;
} else {
return TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![ i ],
};
}
}
}
TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![],
}
}
}
}
fn goto(&mut self, new_cur: TreeCursor) -> TreeNavResult {
let old_cur = self.cursor.get();
if let Some(i) = old_cur.idx {
if i < self.data.len() as isize {
self.data.get_mut(i as usize).write().unwrap().goto(TreeCursor::none());
}
}
match new_cur.tree_addr.len() {
0 => {
self.cursor.set(ListCursor {
mode: new_cur.leaf_mode,
idx: None,
});
TreeNavResult::Continue
}
1 => {
let idx = crate::utils::modulo(new_cur.tree_addr[0], if new_cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 } + self.data.len() as isize);
self.cursor.set(ListCursor {
mode: new_cur.leaf_mode,
idx: Some(idx),
});
if new_cur.leaf_mode == ListCursorMode::Select && self.data.len() > 0 {
self.data
.get_mut(idx as usize)
.write().unwrap()
.goto(TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![]
});
}
TreeNavResult::Continue
}
_ => {
if self.data.len() > 0 {
let idx = crate::utils::modulo(new_cur.tree_addr[0], self.data.len() as isize);
self.cursor.set(ListCursor {
mode: ListCursorMode::Select,
idx: Some(idx),
});
self.data
.get_mut(idx as usize)
.write().unwrap()
.goto(TreeCursor {
leaf_mode: new_cur.leaf_mode,
tree_addr: new_cur.tree_addr[1..].iter().cloned().collect(),
});
} else {
self.cursor.set(ListCursor::home());
}
TreeNavResult::Continue
}
}
}
fn goby(&mut self, direction: Vector2<isize>) -> TreeNavResult {
let mut cur = self.get_cursor();
let gravity = true;
match cur.tree_addr.len() {
0 => {
if direction.y < 0 {
// up
self.cursor.set(ListCursor::none());
TreeNavResult::Exit
} else if direction.y > 0 {
// dn
self.cursor.set(ListCursor {
mode: if self.data.len() > 0 { cur.leaf_mode } else { ListCursorMode::Insert },
idx: Some(0)
});
self.goby(Vector2::new(direction.x, direction.y-1));
TreeNavResult::Continue
} else {
TreeNavResult::Continue
}
},
1 => {
if direction.y > 0 {
// dn
if cur.tree_addr[0] < self.data.len() as isize {
if self.data
.get_mut(cur.tree_addr[0] as usize)
.write().unwrap()
.goby(Vector2::new(direction.x, direction.y))
== TreeNavResult::Continue {
self.cursor.set(ListCursor {
mode: ListCursorMode::Select,
idx: Some(cur.tree_addr[0])
});
self.set_leaf_mode(cur.leaf_mode);
}
}
TreeNavResult::Continue
} else if direction.y < 0 {
// up
self.cursor.set(ListCursor {
mode: cur.leaf_mode,
idx: None
});
TreeNavResult::Exit
} else {
// horizontal
if (cur.tree_addr[0]+direction.x >= 0) &&
(cur.tree_addr[0]+direction.x <
self.data.len() as isize
+ if cur.leaf_mode == ListCursorMode::Insert { 1 } else { 0 })
{
let idx = cur.tree_addr[0] + direction.x;
let mut new_addr = Vec::new();
match cur.leaf_mode {
ListCursorMode::Select => {
let cur_item = self.data.get(cur.tree_addr[0] as usize);
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::Max);
let new_item = self.data
.get_mut(idx as usize);
let height = new_item.read().unwrap().get_height(
if direction.x < 0 {
&TreeHeightOp::Q
} else {
&TreeHeightOp::P
}
);
new_addr.push(idx);
if gravity && cur_height < 2 {
for _ in 1..height {
new_addr.push( if direction.x >= 0 {
0
} else {
-1
});
}
}
}
ListCursorMode::Insert => {
let gravity = false;
if direction.x > 0
{
if (cur.tree_addr[0] as usize) < self.data.len() {
let cur_item = self.data.get(cur.tree_addr[0] as usize);
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::P);
if gravity && cur_height > 1 {
new_addr.push( cur.tree_addr[0] );
new_addr.push(0);
} else {
new_addr.push( idx );
}
}
} else {
if (idx as usize) < self.data.len() {
let pxv_item = self.data.get(idx as usize);
let pxv_height = pxv_item.read().unwrap().get_height(&TreeHeightOp::P);
if gravity && pxv_height > 1 {
new_addr.push( idx );
new_addr.push( -1 );
} else {
new_addr.push( idx );
}
}
}
}
}
if self.data.len() == 0 {
cur.leaf_mode = ListCursorMode::Insert
}
cur.tree_addr = new_addr;
self.goto(cur);
TreeNavResult::Continue
} else {
self.cursor.set(ListCursor {
mode: cur.leaf_mode,
idx: None
});
self.cursor.set(ListCursor::none());
TreeNavResult::Exit
}
}
},
depth => {
// nested
if cur.tree_addr[0] < self.data.len() as isize {
let cur_item = self.data
.get_mut(cur.tree_addr[0] as usize);
let result = cur_item.write().unwrap().goby(direction);
match result
{
TreeNavResult::Exit => {
if direction.y < 0 {
// up
self.cursor.set(ListCursor {
mode: cur.leaf_mode,
idx: Some(cur.tree_addr[0])
});
TreeNavResult::Continue
} else if direction.y > 0 {
// dn
TreeNavResult::Continue
} else {
// horizontal
if (cur.tree_addr[0]+direction.x >= 0) &&
(cur.tree_addr[0]+direction.x < self.data.len() as isize)
{
let mut new_addr = Vec::new();
if direction.x < 0 {
let pxv_item = self.data
.get_mut(cur.tree_addr[0] as usize - 1);
let pxv_height = pxv_item.read().unwrap().get_height(&TreeHeightOp::Q) as isize;
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::P) as isize;
let dist_from_ground = cur_height - (depth as isize - 1);
let n_steps_down =
if gravity {
pxv_height - dist_from_ground
} else {
depth as isize - 1
};
new_addr.push( cur.tree_addr[0] - 1 );
for _i in 0..n_steps_down {
new_addr.push( -1 );
}
} else {
let nxd_item = self.data
.get_mut(cur.tree_addr[0] as usize + 1);
let cur_height = cur_item.read().unwrap().get_height(&TreeHeightOp::Q) as isize;
let nxd_height = nxd_item.read().unwrap().get_height(&TreeHeightOp::P) as isize;
let dist_from_ground = cur_height - (depth as isize - 1);
let n_steps_down =
if gravity {
nxd_height - dist_from_ground
} else {
depth as isize - 1
};
new_addr.push( cur.tree_addr[0] + 1 );
for _i in 0..n_steps_down {
new_addr.push( 0 );
}
}
drop(cur_item);
cur.tree_addr = new_addr;
self.goto(cur)
} else {
self.cursor.set(ListCursor {
mode: cur.leaf_mode,
idx: None
});
self.cursor.set(ListCursor::none());
TreeNavResult::Exit
}
}
}
TreeNavResult::Continue => TreeNavResult::Continue
}
} else {
self.cursor.set(
ListCursor {
mode: ListCursorMode::Insert,
idx: Some(0)
}
);
TreeNavResult::Continue
}
}
}
}
}