more improvements for ListEditor

fix some glitches by refactoring ListCursor: mode is now always present, only idx is optional
This commit is contained in:
Michael Sippel 2021-08-26 08:20:51 +02:00
parent 5eefcbb4d1
commit cec7b4a0a0
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 343 additions and 370 deletions

View file

@ -9,14 +9,14 @@ pub enum ListCursorMode {
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
pub struct ListCursor { pub struct ListCursor {
pub mode: ListCursorMode, pub mode: ListCursorMode,
pub idx: usize pub idx: Option<usize>
} }
impl Default for ListCursor { impl Default for ListCursor {
fn default() -> Self { fn default() -> Self {
ListCursor { ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Select,
idx: 0 idx: None
} }
} }
} }

View file

@ -40,7 +40,7 @@ pub struct ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
{ {
cursor: SingletonBuffer<Option<ListCursor>>, cursor: SingletonBuffer<ListCursor>,
data: VecBuffer<Arc<RwLock<ItemEditor>>>, data: VecBuffer<Arc<RwLock<ItemEditor>>>,
data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>>, data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>>,
make_item_editor: FnMakeItemEditor, make_item_editor: FnMakeItemEditor,
@ -54,206 +54,213 @@ impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItem
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
{ {
fn get_cursor(&self) -> Option<TreeCursor> { fn get_cursor(&self) -> TreeCursor {
if let Some(cur) = self.cursor.get() { let cur = self.cursor.get();
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert |
ListCursorMode::Select => { ListCursorMode::Select => {
Some(TreeCursor { TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: vec![ cur.idx ] tree_addr: if let Some(i) = cur.idx { vec![ i ] } else { vec![] }
}) }
}, },
ListCursorMode::Modify => { ListCursorMode::Modify => {
if cur.idx < self.data.len() { if let Some(i) = cur.idx {
if let Some(mut sub_cur) = self.data.get(cur.idx).read().unwrap().get_cursor() { if i < self.data.len() {
sub_cur.tree_addr.insert(0, cur.idx); let mut sub_cur = self.data.get(i).read().unwrap().get_cursor();
Some(sub_cur) sub_cur.tree_addr.insert(0, i);
} else { return sub_cur;
Some(TreeCursor {
leaf_mode: cur.mode,
tree_addr: vec![ cur.idx ]
})
}
} else {
None
} }
} }
TreeCursor {
leaf_mode: cur.mode,
tree_addr: vec![]
}
} }
} else {
None
} }
} }
fn goto(&mut self, cursor: Option<TreeCursor>) -> TreeNavResult { fn goto(&mut self, new_cur: TreeCursor) -> TreeNavResult {
if let Some(old_cur) = self.cursor.get() { let old_cur = self.cursor.get();
if old_cur.mode == ListCursorMode::Modify { if old_cur.mode == ListCursorMode::Modify {
let ce = self.data.get_mut(old_cur.idx); if let Some(i) = old_cur.idx {
let ce = self.data.get_mut(i);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
cur_edit.goto(None); cur_edit.goto(TreeCursor::default());
} }
} }
if let Some(new_cur) = cursor { if new_cur.tree_addr.len() == 1 {
if new_cur.tree_addr.len() == 1 { self.cursor.set(ListCursor{
self.cursor.set(Some(ListCursor{ mode: new_cur.leaf_mode,
mode: new_cur.leaf_mode, idx: Some(new_cur.tree_addr[0])
idx: new_cur.tree_addr[0] });
})); TreeNavResult::Continue
TreeNavResult::Continue } else if new_cur.tree_addr.len() > 1 && new_cur.tree_addr[0] < self.data.len() {
} else if new_cur.tree_addr[0] < self.data.len() { self.cursor.set(ListCursor {
self.cursor.set(Some(ListCursor { mode: ListCursorMode::Modify,
mode: ListCursorMode::Modify, idx: Some(new_cur.tree_addr[0])
idx: new_cur.tree_addr[0] });
}));
let ne = self.data.get_mut(new_cur.tree_addr[0]); let ne = self.data.get_mut(new_cur.tree_addr[0]);
let mut nxt_edit = ne.write().unwrap(); let mut nxt_edit = ne.write().unwrap();
nxt_edit.goto( nxt_edit.goto(
Some(TreeCursor { TreeCursor {
leaf_mode: new_cur.leaf_mode, leaf_mode: new_cur.leaf_mode,
tree_addr: new_cur.tree_addr[1..].iter().cloned().collect() tree_addr: new_cur.tree_addr[1..].iter().cloned().collect()
})); });
TreeNavResult::Continue TreeNavResult::Continue
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor {
mode: new_cur.leaf_mode,
idx: None
});
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
fn goto_end(&mut self) -> TreeNavResult { fn goto_end(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let mut cur = self.cursor.get();
if cur.idx < self.data.len() { let i = cur.idx.unwrap_or(0);
match cur.mode { if i < self.data.len() {
ListCursorMode::Insert => { match cur.mode {
if cur.idx < self.data.len() { ListCursorMode::Insert => {
self.cursor.set(Some( if i < self.data.len() || cur.idx.is_none() {
ListCursor { cur.idx = Some(self.data.len());
mode: ListCursorMode::Insert, self.cursor.set(cur);
idx: self.data.len() TreeNavResult::Continue
} } else {
)); self.cursor.set(ListCursor::default());
TreeNavResult::Continue TreeNavResult::Exit
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
} }
ListCursorMode::Select => { }
if cur.idx+1 < self.data.len() { ListCursorMode::Select => {
self.cursor.set(Some( if i+1 < self.data.len() || cur.idx.is_none() {
ListCursor { cur.idx = Some(self.data.len()-1);
mode: ListCursorMode::Select, self.cursor.set(cur);
idx: self.data.len()-1 TreeNavResult::Continue
} } else {
)); self.cursor.set(ListCursor::default());
TreeNavResult::Continue TreeNavResult::Exit
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
} }
ListCursorMode::Modify => { }
let ce = self.data.get_mut(cur.idx); ListCursorMode::Modify => {
let mut cur_edit = ce.write().unwrap(); let ce = self.data.get_mut(i);
let cur_mode = if let Some(c) = cur_edit.get_cursor() { c.leaf_mode } else { ListCursorMode::Select }; let mut cur_edit = ce.write().unwrap();
let cur_mode = cur_edit.get_cursor().leaf_mode;
match cur_edit.goto_end() { match cur_edit.goto_end() {
TreeNavResult::Continue => { TreeNavResult::Continue => {
TreeNavResult::Continue TreeNavResult::Continue
} }
TreeNavResult::Exit => { TreeNavResult::Exit => {
if cur.idx+1 < self.data.len() { if let Some(i) = cur.idx {
if i+1 < self.data.len() {
cur_edit.up(); cur_edit.up();
drop(cur_edit); drop(cur_edit);
self.set_mode(cur_mode);
self.nexd(); self.nexd();
self.dn(); self.set_mode(ListCursorMode::Modify);
self.goto_end();
let ne = self.get_item().unwrap();
let mut nxd_edit = ne.write().unwrap();
nxd_edit.goto(
TreeCursor {
leaf_mode: cur_mode,
tree_addr: vec![]
}
);
nxd_edit.goto_end();
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
} }
} }
} }
} }
} else {
// goto right neighbours end
TreeNavResult::Exit
} }
} else { } else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
fn goto_home(&mut self) -> TreeNavResult { fn goto_home(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let cur = self.cursor.get();
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert |
ListCursorMode::Select => { ListCursorMode::Select => {
if cur.idx > 0 { if cur.idx != Some(0) {
self.cursor.set(Some( self.cursor.set(
ListCursor { ListCursor {
mode: cur.mode, mode: cur.mode,
idx: 0 idx: Some(0)
} }
)); );
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
}
} }
ListCursorMode::Modify => { }
let ce = self.get_item().unwrap(); ListCursorMode::Modify => {
let mut cur_edit = ce.write().unwrap(); let ce = self.get_item().unwrap();
let cur_mode = if let Some(c) = cur_edit.get_cursor() { c.leaf_mode } else { ListCursorMode::Select }; let mut cur_edit = ce.write().unwrap();
let cur_mode = cur_edit.get_cursor().leaf_mode;
match cur_edit.goto_home() { match cur_edit.goto_home() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
if cur.idx > 0 { if let Some(i) = cur.idx {
if i > 0 {
cur_edit.up(); cur_edit.up();
drop(cur_edit); drop(cur_edit);
self.set_mode(cur_mode);
self.pxev(); self.pxev();
self.dn(); self.set_mode(ListCursorMode::Modify);
let pe = self.get_item().unwrap();
let mut pxv_edit = pe.write().unwrap();
pxv_edit.goto(
TreeCursor {
leaf_mode: cur_mode,
tree_addr: vec![]
}
);
pxv_edit.goto_home();
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
} }
TreeNavResult::Continue => TreeNavResult::Continue
} }
TreeNavResult::Continue => TreeNavResult::Continue
} }
} }
} else {
TreeNavResult::Exit
} }
} }
fn up(&mut self) -> TreeNavResult { fn up(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let cur = self.cursor.get();
if cur.mode == ListCursorMode::Modify { if cur.mode == ListCursorMode::Modify {
let ce = self.data.get_mut(cur.idx); if let Some(i) = cur.idx {
let ce = self.data.get_mut(i);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
let mode = cur_edit.get_cursor().leaf_mode;
let mode =
if let Some(c) = cur_edit.get_cursor() {
c.leaf_mode
} else {
ListCursorMode::Select
};
match cur_edit.up() { match cur_edit.up() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
@ -262,100 +269,85 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TreeNavResult::Continue => {} TreeNavResult::Continue => {}
} }
TreeNavResult::Continue return TreeNavResult::Continue;
} else {
self.cursor.set(None);
TreeNavResult::Exit
} }
} else {
TreeNavResult::Exit
} }
self.cursor.set(ListCursor {
mode: cur.mode,
idx: None
});
TreeNavResult::Exit
} }
fn dn(&mut self) -> TreeNavResult { fn dn(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let cur = self.cursor.get();
match cur.mode { match cur.mode {
ListCursorMode::Insert | ListCursorMode::Insert |
ListCursorMode::Select => { ListCursorMode::Select => {
if cur.idx < self.data.len() { if let Some(i) = cur.idx {
self.cursor.set(Some(ListCursor { if i < self.data.len() {
mode: ListCursorMode::Modify, self.set_mode(ListCursorMode::Modify);
idx: cur.idx self.data.get_mut(i).write().unwrap().goto(
})); TreeCursor {
self.data.get_mut(cur.idx).write().unwrap().goto(
Some(TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: vec![ 0 ] tree_addr: vec![ 0 ]
}) }
); );
} }
} }
ListCursorMode::Modify => {
let ce = self.data.get_mut(cur.idx);
let mut cur_edit = ce.write().unwrap();
cur_edit.dn();
}
} }
TreeNavResult::Continue ListCursorMode::Modify => {
} else { self.get_item().unwrap().write().unwrap().dn();
self.cursor.set(Some(ListCursor { }
mode: ListCursorMode::Insert,
idx: 0 // todo: smart prediction
}));
TreeNavResult::Continue
} }
TreeNavResult::Continue
} }
fn pxev(&mut self) -> TreeNavResult { fn pxev(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let mut cur = self.cursor.get();
if let Some(i) = cur.idx {
match cur.mode { match cur.mode {
ListCursorMode::Insert => { ListCursorMode::Insert |
if cur.idx > 0 {
self.cursor.set(Some(ListCursor {
mode: ListCursorMode::Insert,
idx: cur.idx - 1
}));
TreeNavResult::Continue
} else {
self.cursor.set(None);
TreeNavResult::Exit
}
}
ListCursorMode::Select => { ListCursorMode::Select => {
if cur.idx > 0 { if i > 0 {
self.cursor.set(Some(ListCursor { cur.idx = Some(i - 1);
mode: ListCursorMode::Select, self.cursor.set(cur);
idx: cur.idx - 1
}));
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
ListCursorMode::Modify => { ListCursorMode::Modify => {
let ce = self.get_item().unwrap(); let ce = self.get_item().unwrap();
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
let cur_mode = if let Some(c) = cur_edit.get_cursor() { c.leaf_mode } else { ListCursorMode::Select }; let cur_mode = cur_edit.get_cursor().leaf_mode;
match cur_edit.pxev() { match cur_edit.pxev() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
if cur.idx > 0 { drop(cur_edit);
cur_edit.up(); if i > 0 {
drop(cur_edit); self.up();
self.set_mode(cur_mode);
self.pxev(); self.pxev();
self.dn(); self.set_mode(ListCursorMode::Modify);
self.goto_end();
let pe = self.get_item().unwrap();
let mut pxv_edit = pe.write().unwrap();
pxv_edit.goto(
TreeCursor {
leaf_mode: cur_mode,
tree_addr: vec![]
}
);
pxv_edit.goto_end();
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} },
TreeNavResult::Continue => TreeNavResult::Continue TreeNavResult::Continue => TreeNavResult::Continue
} }
} }
@ -366,40 +358,37 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
fn nexd(&mut self) -> TreeNavResult { fn nexd(&mut self) -> TreeNavResult {
if let Some(cur) = self.cursor.get() { let mut cur = self.cursor.get();
if let Some(i) = cur.idx {
match cur.mode { match cur.mode {
ListCursorMode::Insert => { ListCursorMode::Insert => {
if cur.idx < self.data.len() { if i < self.data.len() {
self.cursor.set(Some(ListCursor { cur.idx = Some(i + 1);
mode: ListCursorMode::Insert, self.cursor.set(cur);
idx: cur.idx + 1
}));
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
ListCursorMode::Select => { ListCursorMode::Select => {
if cur.idx+1 < self.data.len() { if i+1 < self.data.len() {
self.cursor.set(Some(ListCursor { cur.idx = Some(i + 1);
mode: ListCursorMode::Select, self.cursor.set(cur);
idx: cur.idx + 1
}));
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
ListCursorMode::Modify => { ListCursorMode::Modify => {
let ce = self.data.get(cur.idx); let ce = self.data.get(i);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
let cur_mode = if let Some(c) = cur_edit.get_cursor() { c.leaf_mode } else { ListCursorMode::Select }; let cur_mode = cur_edit.get_cursor().leaf_mode;
match cur_edit.nexd() { match cur_edit.nexd() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
if cur.idx+1 < self.data.len() { if i+1 < self.data.len() {
cur_edit.up(); cur_edit.up();
drop(cur_edit); drop(cur_edit);
drop(ce); drop(ce);
@ -409,7 +398,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.dn(); self.dn();
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(None); self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
@ -432,25 +421,24 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
if let Some(cur) = self.cursor.get() { let mut cur = self.cursor.get();
if let Some(idx) = cur.idx {
match cur.mode { match cur.mode {
ListCursorMode::Insert => { ListCursorMode::Insert => {
match event { match event {
TerminalEvent::Input(Event::Key(Key::Backspace)) => { TerminalEvent::Input(Event::Key(Key::Backspace)) => {
if cur.idx > 0 { if idx > 0 {
self.data.remove(cur.idx-1); self.data.remove(idx-1);
self.cursor.set(Some(ListCursor { cur.idx = Some(idx-1);
mode: ListCursorMode::Insert, self.cursor.set(cur);
idx: cur.idx-1
}));
TerminalEditorResult::Continue TerminalEditorResult::Continue
} else { } else {
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }
} }
TerminalEvent::Input(Event::Key(Key::Delete)) => { TerminalEvent::Input(Event::Key(Key::Delete)) => {
if cur.idx < self.data.len() { if idx < self.data.len() {
self.data.remove(cur.idx); self.data.remove(idx);
TerminalEditorResult::Continue TerminalEditorResult::Continue
} else { } else {
TerminalEditorResult::Exit TerminalEditorResult::Exit
@ -458,24 +446,20 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
TerminalEvent::Input(Event::Key(Key::Char('\t'))) | TerminalEvent::Input(Event::Key(Key::Char('\t'))) |
TerminalEvent::Input(Event::Key(Key::Insert)) => { TerminalEvent::Input(Event::Key(Key::Insert)) => {
let l = self.data.len();
self.set_mode(ListCursorMode::Select); self.set_mode(ListCursorMode::Select);
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
_ => { _ => {
let new_edit = (self.make_item_editor)(); let new_edit = (self.make_item_editor)();
self.data.insert(cur.idx, new_edit.clone()); self.data.insert(idx, new_edit.clone());
self.cursor.set(Some(ListCursor { self.dn();
mode: ListCursorMode::Modify,
idx: cur.idx
}));
match new_edit.write().unwrap().handle_terminal_event(event) { match new_edit.write().unwrap().handle_terminal_event(event) {
TerminalEditorResult::Exit => { TerminalEditorResult::Exit => {
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: cur.idx+1 idx: Some(idx+1)
})); });
} }
_ => {} _ => {}
} }
@ -487,40 +471,39 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char('\t'))) | TerminalEvent::Input(Event::Key(Key::Char('\t'))) |
TerminalEvent::Input(Event::Key(Key::Insert)) => { TerminalEvent::Input(Event::Key(Key::Insert)) => {
self.cursor.set(Some(ListCursor { self.set_mode(ListCursorMode::Insert);
mode: ListCursorMode::Insert, TerminalEditorResult::Continue
idx: cur.idx
}));
} }
TerminalEvent::Input(Event::Key(Key::Delete)) => { TerminalEvent::Input(Event::Key(Key::Delete)) => {
self.data.remove(cur.idx); self.data.remove(idx);
if self.data.len() == 0 { if self.data.len() == 0 {
self.cursor.set(Some(ListCursor::default())); self.cursor.set(ListCursor::default());
} else if cur.idx == self.data.len() { } else if idx == self.data.len() {
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Select, mode: ListCursorMode::Select,
idx: cur.idx-1 idx: Some(idx-1)
})); });
} }
TerminalEditorResult::Continue
}
_ => {
TerminalEditorResult::Continue
} }
_ => {}
} }
TerminalEditorResult::Continue
} }
ListCursorMode::Modify => { ListCursorMode::Modify => {
let mut ce = self.data.get_mut(cur.idx); let mut ce = self.data.get_mut(idx);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
match event { match event {
TerminalEvent::Input(Event::Key(Key::Char(' '))) => { TerminalEvent::Input(Event::Key(Key::Char(' '))) => {
// split.. // split..
cur_edit.up(); cur_edit.up();
drop(cur_edit); drop(cur_edit);
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: cur.idx+1 idx: Some(idx+1)
})); });
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
TerminalEvent::Input(Event::Key(Key::Backspace)) => { TerminalEvent::Input(Event::Key(Key::Backspace)) => {
@ -528,11 +511,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
TerminalEditorResult::Exit => { TerminalEditorResult::Exit => {
drop(cur_edit); drop(cur_edit);
drop(ce); drop(ce);
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: cur.idx idx: Some(idx)
})); });
self.data.remove(cur.idx); // todo: join instead of remove self.data.remove(idx); // todo: join instead of remove
} }
TerminalEditorResult::Continue => { TerminalEditorResult::Continue => {
} }
@ -544,7 +527,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
} }
} else { } else {
TerminalEditorResult::Continue TerminalEditorResult::Continue
} }
} }
} }
@ -557,9 +540,9 @@ enum ListEditorViewSegment {
} }
struct ListEditorView { struct ListEditorView {
cursor: Arc<dyn SingletonView<Item = Option<ListCursor>>>, cursor: Arc<dyn SingletonView<Item = ListCursor>>,
data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>, data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
cur_cursor: Option<ListCursor>, cur_cursor: ListCursor,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>, cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
proj_helper: ProjectionHelper<usize, Self> proj_helper: ProjectionHelper<usize, Self>
@ -573,46 +556,42 @@ impl SequenceView for ListEditorView {
type Item = ListEditorViewSegment; type Item = ListEditorViewSegment;
fn len(&self) -> Option<usize> { fn len(&self) -> Option<usize> {
if let Some(cur) = self.cur_cursor { match self.cursor.get().mode {
match cur.mode { ListCursorMode::Insert => Some(self.data.len()? + 1),
ListCursorMode::Insert => Some(self.data.len()? + 1), _ => self.data.len()
_ => self.data.len()
}
} else {
self.data.len()
} }
} }
fn get(&self, idx: &usize) -> Option<Self::Item> { fn get(&self, idx: &usize) -> Option<Self::Item> {
Some( Some(
if let Some(cur) = self.cur_cursor { if let Some(cur) = self.cur_cursor.idx {
match cur.mode { match self.cur_cursor.mode {
ListCursorMode::Select => { ListCursorMode::Select => {
if *idx == cur.idx { if *idx == cur {
ListEditorViewSegment::Select(self.data.get(idx)?) ListEditorViewSegment::Select(self.data.get(&idx)?)
} else { } else {
ListEditorViewSegment::View(self.data.get(idx)?) ListEditorViewSegment::View(self.data.get(&idx)?)
} }
} }
ListCursorMode::Insert => { ListCursorMode::Insert => {
if *idx < cur.idx { if *idx < cur {
ListEditorViewSegment::View(self.data.get(idx)?) ListEditorViewSegment::View(self.data.get(&idx)?)
} else if *idx == cur.idx { } else if *idx == cur {
ListEditorViewSegment::InsertCursor ListEditorViewSegment::InsertCursor
} else { } else {
ListEditorViewSegment::View(self.data.get(&(idx-1))?) ListEditorViewSegment::View(self.data.get(&(idx-1))?)
} }
} }
ListCursorMode::Modify => { ListCursorMode::Modify => {
if *idx == cur.idx { if *idx == cur {
ListEditorViewSegment::Modify(self.data.get(idx)?) ListEditorViewSegment::Modify(self.data.get(&idx)?)
} else { } else {
ListEditorViewSegment::View(self.data.get(idx)?) ListEditorViewSegment::View(self.data.get(&idx)?)
} }
} }
} }
} else { } else {
ListEditorViewSegment::View(self.data.get(idx)?) ListEditorViewSegment::View(self.data.get(&idx)?)
} }
) )
} }
@ -620,14 +599,14 @@ impl SequenceView for ListEditorView {
impl ListEditorView { impl ListEditorView {
fn new( fn new(
cursor_port: OuterViewPort<dyn SingletonView<Item = Option<ListCursor>>>, cursor_port: OuterViewPort<dyn SingletonView<Item = ListCursor>>,
data_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>, data_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
out_port: InnerViewPort<dyn SequenceView<Item = ListEditorViewSegment>> out_port: InnerViewPort<dyn SequenceView<Item = ListEditorViewSegment>>
) -> Arc<RwLock<Self>> { ) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new( let proj = Arc::new(RwLock::new(
ListEditorView { ListEditorView {
cur_cursor: None, cur_cursor: ListCursor::default(),
cursor: proj_helper.new_singleton_arg( cursor: proj_helper.new_singleton_arg(
0, 0,
cursor_port, cursor_port,
@ -635,45 +614,7 @@ impl ListEditorView {
let old_cursor = s.cur_cursor; let old_cursor = s.cur_cursor;
let new_cursor = s.cursor.get(); let new_cursor = s.cursor.get();
s.cur_cursor = new_cursor; s.cur_cursor = new_cursor;
/*
let mut begin = std::cmp::min(
if let Some(cur) = self.old_cursor {
cur.idx
} else {
usize::MAX
},
if let Some(cur) = self.new_cursor {
cur.idx
} else {
usize::MAX
}
);
let mut end =
/*
match (old_cursor, new_cursor) {
(ListEditorCursor::None, ListEditorCursor::None) => usize::MAX,
(ListEditorCursor::Select(old_pos), ListEditorCursor::Select(new_pos)) => max(old_pos, new_pos),
(ListEditorCursor::Edit(old_pos), ListEditorCursor::Edit(new_pos)) => max(old_pos, new_pos),
(ListEditorCursor::Insert(old_pos), ListEditorCursor::Insert(new_pos)) => max(old_pos, new_pos),
(ListEditorCursor::)
};
*/
std::cmp::max(
match old_cursor {
ListEditorCursor::None => 0,
ListEditorCursor::Select(c) => c,
ListEditorCursor::Insert(c) => c+1,
ListEditorCursor::Edit(c) => c
},
match new_cursor {
ListEditorCursor::None => 0,
ListEditorCursor::Select(c) => c,
ListEditorCursor::Insert(c) => c+1,
ListEditorCursor::Edit(c) => c
}
);
*/
s.cast.notify_each( s.cast.notify_each(
0 ..= s.data.len().unwrap_or(0)+1 0 ..= s.data.len().unwrap_or(0)+1
); );
@ -682,10 +623,10 @@ impl ListEditorView {
1, 1,
data_port, data_port,
|s: &mut Self, idx| { |s: &mut Self, idx| {
if let Some(cur) = s.cur_cursor { if let Some(cur_idx) = s.cur_cursor.idx {
match cur.mode { match s.cur_cursor.mode {
ListCursorMode::Insert => { ListCursorMode::Insert => {
if *idx < cur.idx { if *idx < cur_idx {
s.cast.notify(idx); s.cast.notify(idx);
} else { } else {
s.cast.notify(&(*idx + 1)); s.cast.notify(&(*idx + 1));
@ -800,7 +741,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
let cursor_port = ViewPort::new(); let cursor_port = ViewPort::new();
let data_port = ViewPort::new(); let data_port = ViewPort::new();
let mut cursor = SingletonBuffer::new(Some(ListCursor::default()), cursor_port.inner()); let mut cursor = SingletonBuffer::new(ListCursor::default(), cursor_port.inner());
let mut data = VecBuffer::<Arc<RwLock<ItemEditor>>>::new(data_port.inner()); let mut data = VecBuffer::<Arc<RwLock<ItemEditor>>>::new(data_port.inner());
let data_sequence_port = data_port.into_outer().to_sequence(); let data_sequence_port = data_port.into_outer().to_sequence();
@ -842,53 +783,45 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
} }
fn get_item(&self) -> Option<Arc<RwLock<ItemEditor>>> { fn get_item(&self) -> Option<Arc<RwLock<ItemEditor>>> {
if let Some(cur) = self.cursor.get() { if let Some(idx) = self.cursor.get().idx {
if cur.idx < self.data.len() { Some(self.data.get(idx))
Some(self.data.get(cur.idx))
} else {
None
}
} else { } else {
None None
} }
} }
fn set_idx(&mut self, idx: isize) { fn set_idx(&mut self, idx: isize) {
let mode = let cur = self.cursor.get();
if let Some(c) = self.cursor.get() { let mode = cur.mode;
c.mode
} else {
ListCursorMode::Insert
};
if idx < 0 { if idx < 0 {
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode, mode,
idx: (self.data.len() as isize + idx) as usize idx: Some((self.data.len() as isize + idx) as usize)
})); });
} else { } else {
self.cursor.set(Some(ListCursor { self.cursor.set(ListCursor {
mode, mode,
idx: idx as usize idx: Some(idx as usize)
})); });
} }
} }
fn set_mode(&mut self, mode: ListCursorMode) { fn set_mode(&mut self, mode: ListCursorMode) {
if let Some(old_cur) = self.cursor.get() { let mut cur = self.cursor.get();
let l = self.data.len();
if old_cur.idx < l { if cur.mode == ListCursorMode::Insert &&
self.cursor.set(Some(ListCursor { mode != ListCursorMode::Insert
mode, {
idx: old_cur.idx if let Some(idx) = cur.idx {
})); if idx == self.data.len() && idx > 0 {
} else { cur.idx = Some(idx-1);
self.cursor.set(Some(ListCursor { }
mode: ListCursorMode::Select,
idx: l-1
}));
} }
} }
cur.mode = mode;
self.cursor.set(cur);
} }
} }

View file

@ -6,13 +6,31 @@ pub enum TreeNavResult {
Continue, Continue,
Exit Exit
} }
/*
impl From<TreeNavResult> for TerminalEditorResult {
fn from(v: TreeNavResult) -> TerminalEditorResult {
match v {
TreeNavResult::Continue => TerminalEditorResult::Continue,
TreeNavResult::Exit => TerminalEditorResult::Exit
}
}
}
*/
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct TreeCursor { pub struct TreeCursor {
pub leaf_mode: ListCursorMode, pub leaf_mode: ListCursorMode,
pub tree_addr: Vec<usize> pub tree_addr: Vec<usize>
} }
impl Default for TreeCursor {
fn default() -> Self {
TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![]
}
}
}
pub trait TreeNav { pub trait TreeNav {
fn up(&mut self) -> TreeNavResult { fn up(&mut self) -> TreeNavResult {
TreeNavResult::Exit TreeNavResult::Exit
@ -38,12 +56,12 @@ pub trait TreeNav {
TreeNavResult::Exit TreeNavResult::Exit
} }
fn goto(&mut self, new_cursor: Option<TreeCursor>) -> TreeNavResult { fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult {
TreeNavResult::Exit TreeNavResult::Exit
} }
fn get_cursor(&self) -> Option<TreeCursor> { fn get_cursor(&self) -> TreeCursor {
None TreeCursor::default()
} }
} }

View file

@ -28,7 +28,7 @@ use{
TerminalView, TerminalView,
TerminalEditor}, TerminalEditor},
string_editor::{CharEditor}, string_editor::{CharEditor},
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor}, tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle} list::{SExprView, ListCursorMode, ListEditor, ListEditorStyle}
} }
}; };
@ -106,9 +106,9 @@ write::
compositor.write().unwrap().push(magic.offset(Vector2::new(40, 4))); compositor.write().unwrap().push(magic.offset(Vector2::new(40, 4)));
//compositor.write().unwrap().push(magic.offset(Vector2::new(40, 20))); //compositor.write().unwrap().push(magic.offset(Vector2::new(40, 20)));
let monstera_port = monstera::make_monstera(); //let monstera_port = monstera::make_monstera();
compositor.write().unwrap().push(monstera_port.clone()); //compositor.write().unwrap().push(monstera_port.clone());
compositor.write().unwrap().push(monstera_port.offset(Vector2::new(83,0))); //compositor.write().unwrap().push(monstera_port.offset(Vector2::new(83,0)));
} }
@ -129,6 +129,13 @@ write::
let mut te = ListEditor::new(make_sub_editor.clone(), ListEditorStyle::Clist); let mut te = ListEditor::new(make_sub_editor.clone(), ListEditorStyle::Clist);
te.goto(
TreeCursor {
leaf_mode: ListCursorMode::Insert,
tree_addr: vec![ 0 ]
}
);
compositor.write().unwrap().push( compositor.write().unwrap().push(
te.get_term_view() te.get_term_view()
.offset(cgmath::Vector2::new(40,y)) .offset(cgmath::Vector2::new(40,y))
@ -255,13 +262,28 @@ write::
*/ */
}, },
ev => { ev => {
te.handle_terminal_event(&ev); if te.get_cursor().leaf_mode == ListCursorMode::Select {
match ev {
TerminalEvent::Input(Event::Key(Key::Char('l'))) => { te.up(); },
TerminalEvent::Input(Event::Key(Key::Char('a'))) => { te.dn(); },
TerminalEvent::Input(Event::Key(Key::Char('i'))) => { te.pxev(); },
TerminalEvent::Input(Event::Key(Key::Char('e'))) => { te.nexd(); },
TerminalEvent::Input(Event::Key(Key::Char('u'))) => { te.goto_home(); },
TerminalEvent::Input(Event::Key(Key::Char('o'))) => { te.goto_end(); },
_ => {
te.handle_terminal_event(&ev);
}
}
} else {
te.handle_terminal_event(&ev);
}
} }
_ => {}
} }
status_chars.clear(); status_chars.clear();
if let Some(cur) = te.get_cursor() { let cur = te.get_cursor();
if cur.tree_addr.len() > 0 {
status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true)))); status_chars.push(TerminalAtom::new('@', TerminalStyle::fg_color((120, 80, 80)).add(TerminalStyle::bold(true))));
for x in cur.tree_addr { for x in cur.tree_addr {
for c in format!("{}", x).chars() { for c in format!("{}", x).chars() {