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> { self.addr_port.clone() } fn get_mode_view(&self) -> OuterViewPort> { 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) -> 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 } } } } }