more improvements for ListEditor
fix some glitches by refactoring ListCursor: mode is now always present, only idx is optional
This commit is contained in:
parent
5eefcbb4d1
commit
cec7b4a0a0
4 changed files with 343 additions and 370 deletions
|
@ -9,14 +9,14 @@ pub enum ListCursorMode {
|
|||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub struct ListCursor {
|
||||
pub mode: ListCursorMode,
|
||||
pub idx: usize
|
||||
pub idx: Option<usize>
|
||||
}
|
||||
|
||||
impl Default for ListCursor {
|
||||
fn default() -> Self {
|
||||
ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: 0
|
||||
mode: ListCursorMode::Select,
|
||||
idx: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ pub struct ListEditor<ItemEditor, FnMakeItemEditor>
|
|||
where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|
||||
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
|
||||
{
|
||||
cursor: SingletonBuffer<Option<ListCursor>>,
|
||||
cursor: SingletonBuffer<ListCursor>,
|
||||
data: VecBuffer<Arc<RwLock<ItemEditor>>>,
|
||||
data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>>,
|
||||
make_item_editor: FnMakeItemEditor,
|
||||
|
@ -54,206 +54,213 @@ impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItem
|
|||
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
||||
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
|
||||
{
|
||||
fn get_cursor(&self) -> Option<TreeCursor> {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
Some(TreeCursor {
|
||||
leaf_mode: cur.mode,
|
||||
tree_addr: vec![ cur.idx ]
|
||||
})
|
||||
},
|
||||
ListCursorMode::Modify => {
|
||||
if cur.idx < self.data.len() {
|
||||
if let Some(mut sub_cur) = self.data.get(cur.idx).read().unwrap().get_cursor() {
|
||||
sub_cur.tree_addr.insert(0, cur.idx);
|
||||
Some(sub_cur)
|
||||
} else {
|
||||
Some(TreeCursor {
|
||||
leaf_mode: cur.mode,
|
||||
tree_addr: vec![ cur.idx ]
|
||||
})
|
||||
}
|
||||
} else {
|
||||
None
|
||||
fn get_cursor(&self) -> TreeCursor {
|
||||
let cur = self.cursor.get();
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
TreeCursor {
|
||||
leaf_mode: cur.mode,
|
||||
tree_addr: if let Some(i) = cur.idx { vec![ i ] } else { vec![] }
|
||||
}
|
||||
},
|
||||
ListCursorMode::Modify => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i < self.data.len() {
|
||||
let mut sub_cur = self.data.get(i).read().unwrap().get_cursor();
|
||||
sub_cur.tree_addr.insert(0, i);
|
||||
return sub_cur;
|
||||
}
|
||||
}
|
||||
TreeCursor {
|
||||
leaf_mode: cur.mode,
|
||||
tree_addr: vec![]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn goto(&mut self, cursor: Option<TreeCursor>) -> TreeNavResult {
|
||||
if let Some(old_cur) = self.cursor.get() {
|
||||
if old_cur.mode == ListCursorMode::Modify {
|
||||
let ce = self.data.get_mut(old_cur.idx);
|
||||
fn goto(&mut self, new_cur: TreeCursor) -> TreeNavResult {
|
||||
let old_cur = self.cursor.get();
|
||||
if old_cur.mode == ListCursorMode::Modify {
|
||||
if let Some(i) = old_cur.idx {
|
||||
let ce = self.data.get_mut(i);
|
||||
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 {
|
||||
self.cursor.set(Some(ListCursor{
|
||||
mode: new_cur.leaf_mode,
|
||||
idx: new_cur.tree_addr[0]
|
||||
}));
|
||||
TreeNavResult::Continue
|
||||
} else if new_cur.tree_addr[0] < self.data.len() {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Modify,
|
||||
idx: new_cur.tree_addr[0]
|
||||
}));
|
||||
if new_cur.tree_addr.len() == 1 {
|
||||
self.cursor.set(ListCursor{
|
||||
mode: new_cur.leaf_mode,
|
||||
idx: Some(new_cur.tree_addr[0])
|
||||
});
|
||||
TreeNavResult::Continue
|
||||
} else if new_cur.tree_addr.len() > 1 && new_cur.tree_addr[0] < self.data.len() {
|
||||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Modify,
|
||||
idx: Some(new_cur.tree_addr[0])
|
||||
});
|
||||
|
||||
let ne = self.data.get_mut(new_cur.tree_addr[0]);
|
||||
let mut nxt_edit = ne.write().unwrap();
|
||||
let ne = self.data.get_mut(new_cur.tree_addr[0]);
|
||||
let mut nxt_edit = ne.write().unwrap();
|
||||
|
||||
nxt_edit.goto(
|
||||
Some(TreeCursor {
|
||||
leaf_mode: new_cur.leaf_mode,
|
||||
tree_addr: new_cur.tree_addr[1..].iter().cloned().collect()
|
||||
}));
|
||||
nxt_edit.goto(
|
||||
TreeCursor {
|
||||
leaf_mode: new_cur.leaf_mode,
|
||||
tree_addr: new_cur.tree_addr[1..].iter().cloned().collect()
|
||||
});
|
||||
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor {
|
||||
mode: new_cur.leaf_mode,
|
||||
idx: None
|
||||
});
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
|
||||
fn goto_end(&mut self) -> TreeNavResult {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
if cur.idx < self.data.len() {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert => {
|
||||
if cur.idx < self.data.len() {
|
||||
self.cursor.set(Some(
|
||||
ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: self.data.len()
|
||||
}
|
||||
));
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
let mut cur = self.cursor.get();
|
||||
let i = cur.idx.unwrap_or(0);
|
||||
if i < self.data.len() {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert => {
|
||||
if i < self.data.len() || cur.idx.is_none() {
|
||||
cur.idx = Some(self.data.len());
|
||||
self.cursor.set(cur);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx+1 < self.data.len() {
|
||||
self.cursor.set(Some(
|
||||
ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: self.data.len()-1
|
||||
}
|
||||
));
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
ListCursorMode::Select => {
|
||||
if i+1 < self.data.len() || cur.idx.is_none() {
|
||||
cur.idx = Some(self.data.len()-1);
|
||||
self.cursor.set(cur);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.data.get_mut(cur.idx);
|
||||
let mut cur_edit = ce.write().unwrap();
|
||||
let cur_mode = if let Some(c) = cur_edit.get_cursor() { c.leaf_mode } else { ListCursorMode::Select };
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.data.get_mut(i);
|
||||
let mut cur_edit = ce.write().unwrap();
|
||||
let cur_mode = cur_edit.get_cursor().leaf_mode;
|
||||
|
||||
match cur_edit.goto_end() {
|
||||
TreeNavResult::Continue => {
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
TreeNavResult::Exit => {
|
||||
if cur.idx+1 < self.data.len() {
|
||||
match cur_edit.goto_end() {
|
||||
TreeNavResult::Continue => {
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
TreeNavResult::Exit => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i+1 < self.data.len() {
|
||||
cur_edit.up();
|
||||
drop(cur_edit);
|
||||
|
||||
self.set_mode(cur_mode);
|
||||
self.nexd();
|
||||
self.dn();
|
||||
self.goto_end();
|
||||
self.set_mode(ListCursorMode::Modify);
|
||||
|
||||
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
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
} else {
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// goto right neighbours end
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
} else {
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
|
||||
fn goto_home(&mut self) -> TreeNavResult {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx > 0 {
|
||||
self.cursor.set(Some(
|
||||
ListCursor {
|
||||
mode: cur.mode,
|
||||
idx: 0
|
||||
}
|
||||
));
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
let cur = self.cursor.get();
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx != Some(0) {
|
||||
self.cursor.set(
|
||||
ListCursor {
|
||||
mode: cur.mode,
|
||||
idx: Some(0)
|
||||
}
|
||||
);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.get_item().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 };
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.get_item().unwrap();
|
||||
let mut cur_edit = ce.write().unwrap();
|
||||
let cur_mode = cur_edit.get_cursor().leaf_mode;
|
||||
|
||||
match cur_edit.goto_home() {
|
||||
TreeNavResult::Exit => {
|
||||
if cur.idx > 0 {
|
||||
match cur_edit.goto_home() {
|
||||
TreeNavResult::Exit => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i > 0 {
|
||||
cur_edit.up();
|
||||
drop(cur_edit);
|
||||
|
||||
self.set_mode(cur_mode);
|
||||
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
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
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 {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
if cur.mode == ListCursorMode::Modify {
|
||||
let ce = self.data.get_mut(cur.idx);
|
||||
let cur = self.cursor.get();
|
||||
if cur.mode == ListCursorMode::Modify {
|
||||
if let Some(i) = cur.idx {
|
||||
let ce = self.data.get_mut(i);
|
||||
let mut cur_edit = ce.write().unwrap();
|
||||
|
||||
let mode =
|
||||
if let Some(c) = cur_edit.get_cursor() {
|
||||
c.leaf_mode
|
||||
} else {
|
||||
ListCursorMode::Select
|
||||
};
|
||||
let mode = cur_edit.get_cursor().leaf_mode;
|
||||
|
||||
match cur_edit.up() {
|
||||
TreeNavResult::Exit => {
|
||||
|
@ -262,100 +269,85 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
TreeNavResult::Continue => {}
|
||||
}
|
||||
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
TreeNavResult::Exit
|
||||
return TreeNavResult::Continue;
|
||||
}
|
||||
} else {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
|
||||
self.cursor.set(ListCursor {
|
||||
mode: cur.mode,
|
||||
idx: None
|
||||
});
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
|
||||
fn dn(&mut self) -> TreeNavResult {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx < self.data.len() {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Modify,
|
||||
idx: cur.idx
|
||||
}));
|
||||
|
||||
self.data.get_mut(cur.idx).write().unwrap().goto(
|
||||
Some(TreeCursor {
|
||||
let cur = self.cursor.get();
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert |
|
||||
ListCursorMode::Select => {
|
||||
if let Some(i) = cur.idx {
|
||||
if i < self.data.len() {
|
||||
self.set_mode(ListCursorMode::Modify);
|
||||
self.data.get_mut(i).write().unwrap().goto(
|
||||
TreeCursor {
|
||||
leaf_mode: cur.mode,
|
||||
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
|
||||
} else {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: 0 // todo: smart prediction
|
||||
}));
|
||||
TreeNavResult::Continue
|
||||
ListCursorMode::Modify => {
|
||||
self.get_item().unwrap().write().unwrap().dn();
|
||||
}
|
||||
}
|
||||
TreeNavResult::Continue
|
||||
}
|
||||
|
||||
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 {
|
||||
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::Insert |
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx > 0 {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: cur.idx - 1
|
||||
}));
|
||||
if i > 0 {
|
||||
cur.idx = Some(i - 1);
|
||||
self.cursor.set(cur);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.get_item().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() {
|
||||
TreeNavResult::Exit => {
|
||||
if cur.idx > 0 {
|
||||
cur_edit.up();
|
||||
drop(cur_edit);
|
||||
|
||||
self.set_mode(cur_mode);
|
||||
drop(cur_edit);
|
||||
if i > 0 {
|
||||
self.up();
|
||||
self.pxev();
|
||||
self.dn();
|
||||
self.goto_end();
|
||||
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_end();
|
||||
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
},
|
||||
TreeNavResult::Continue => TreeNavResult::Continue
|
||||
}
|
||||
}
|
||||
|
@ -366,40 +358,37 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
}
|
||||
|
||||
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 {
|
||||
ListCursorMode::Insert => {
|
||||
if cur.idx < self.data.len() {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx + 1
|
||||
}));
|
||||
if i < self.data.len() {
|
||||
cur.idx = Some(i + 1);
|
||||
self.cursor.set(cur);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
ListCursorMode::Select => {
|
||||
if cur.idx+1 < self.data.len() {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: cur.idx + 1
|
||||
}));
|
||||
if i+1 < self.data.len() {
|
||||
cur.idx = Some(i + 1);
|
||||
self.cursor.set(cur);
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
let ce = self.data.get(cur.idx);
|
||||
let ce = self.data.get(i);
|
||||
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() {
|
||||
TreeNavResult::Exit => {
|
||||
if cur.idx+1 < self.data.len() {
|
||||
if i+1 < self.data.len() {
|
||||
cur_edit.up();
|
||||
drop(cur_edit);
|
||||
drop(ce);
|
||||
|
@ -409,7 +398,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
self.dn();
|
||||
TreeNavResult::Continue
|
||||
} else {
|
||||
self.cursor.set(None);
|
||||
self.cursor.set(ListCursor::default());
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
}
|
||||
|
@ -432,25 +421,24 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
}
|
||||
|
||||
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 {
|
||||
ListCursorMode::Insert => {
|
||||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Backspace)) => {
|
||||
if cur.idx > 0 {
|
||||
self.data.remove(cur.idx-1);
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx-1
|
||||
}));
|
||||
if idx > 0 {
|
||||
self.data.remove(idx-1);
|
||||
cur.idx = Some(idx-1);
|
||||
self.cursor.set(cur);
|
||||
TerminalEditorResult::Continue
|
||||
} else {
|
||||
TerminalEditorResult::Exit
|
||||
}
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Delete)) => {
|
||||
if cur.idx < self.data.len() {
|
||||
self.data.remove(cur.idx);
|
||||
if idx < self.data.len() {
|
||||
self.data.remove(idx);
|
||||
TerminalEditorResult::Continue
|
||||
} else {
|
||||
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::Insert)) => {
|
||||
let l = self.data.len();
|
||||
self.set_mode(ListCursorMode::Select);
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
_ => {
|
||||
let new_edit = (self.make_item_editor)();
|
||||
self.data.insert(cur.idx, new_edit.clone());
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Modify,
|
||||
idx: cur.idx
|
||||
}));
|
||||
self.data.insert(idx, new_edit.clone());
|
||||
self.dn();
|
||||
|
||||
match new_edit.write().unwrap().handle_terminal_event(event) {
|
||||
TerminalEditorResult::Exit => {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx+1
|
||||
}));
|
||||
idx: Some(idx+1)
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -487,40 +471,39 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Char('\t'))) |
|
||||
TerminalEvent::Input(Event::Key(Key::Insert)) => {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx
|
||||
}));
|
||||
self.set_mode(ListCursorMode::Insert);
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Delete)) => {
|
||||
self.data.remove(cur.idx);
|
||||
self.data.remove(idx);
|
||||
|
||||
if self.data.len() == 0 {
|
||||
self.cursor.set(Some(ListCursor::default()));
|
||||
} else if cur.idx == self.data.len() {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor::default());
|
||||
} else if idx == self.data.len() {
|
||||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: cur.idx-1
|
||||
}));
|
||||
idx: Some(idx-1)
|
||||
});
|
||||
}
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
_ => {
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
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();
|
||||
match event {
|
||||
TerminalEvent::Input(Event::Key(Key::Char(' '))) => {
|
||||
// split..
|
||||
cur_edit.up();
|
||||
drop(cur_edit);
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx+1
|
||||
}));
|
||||
idx: Some(idx+1)
|
||||
});
|
||||
TerminalEditorResult::Continue
|
||||
}
|
||||
TerminalEvent::Input(Event::Key(Key::Backspace)) => {
|
||||
|
@ -528,11 +511,11 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
|
|||
TerminalEditorResult::Exit => {
|
||||
drop(cur_edit);
|
||||
drop(ce);
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor {
|
||||
mode: ListCursorMode::Insert,
|
||||
idx: cur.idx
|
||||
}));
|
||||
self.data.remove(cur.idx); // todo: join instead of remove
|
||||
idx: Some(idx)
|
||||
});
|
||||
self.data.remove(idx); // todo: join instead of remove
|
||||
}
|
||||
TerminalEditorResult::Continue => {
|
||||
}
|
||||
|
@ -557,9 +540,9 @@ enum ListEditorViewSegment {
|
|||
}
|
||||
|
||||
struct ListEditorView {
|
||||
cursor: Arc<dyn SingletonView<Item = Option<ListCursor>>>,
|
||||
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
|
||||
data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
|
||||
cur_cursor: Option<ListCursor>,
|
||||
cur_cursor: ListCursor,
|
||||
|
||||
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
|
||||
proj_helper: ProjectionHelper<usize, Self>
|
||||
|
@ -573,46 +556,42 @@ impl SequenceView for ListEditorView {
|
|||
type Item = ListEditorViewSegment;
|
||||
|
||||
fn len(&self) -> Option<usize> {
|
||||
if let Some(cur) = self.cur_cursor {
|
||||
match cur.mode {
|
||||
ListCursorMode::Insert => Some(self.data.len()? + 1),
|
||||
_ => self.data.len()
|
||||
}
|
||||
} else {
|
||||
self.data.len()
|
||||
match self.cursor.get().mode {
|
||||
ListCursorMode::Insert => Some(self.data.len()? + 1),
|
||||
_ => self.data.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, idx: &usize) -> Option<Self::Item> {
|
||||
Some(
|
||||
if let Some(cur) = self.cur_cursor {
|
||||
match cur.mode {
|
||||
if let Some(cur) = self.cur_cursor.idx {
|
||||
match self.cur_cursor.mode {
|
||||
ListCursorMode::Select => {
|
||||
if *idx == cur.idx {
|
||||
ListEditorViewSegment::Select(self.data.get(idx)?)
|
||||
if *idx == cur {
|
||||
ListEditorViewSegment::Select(self.data.get(&idx)?)
|
||||
} else {
|
||||
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||
ListEditorViewSegment::View(self.data.get(&idx)?)
|
||||
}
|
||||
}
|
||||
ListCursorMode::Insert => {
|
||||
if *idx < cur.idx {
|
||||
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||
} else if *idx == cur.idx {
|
||||
if *idx < cur {
|
||||
ListEditorViewSegment::View(self.data.get(&idx)?)
|
||||
} else if *idx == cur {
|
||||
ListEditorViewSegment::InsertCursor
|
||||
} else {
|
||||
ListEditorViewSegment::View(self.data.get(&(idx-1))?)
|
||||
}
|
||||
}
|
||||
ListCursorMode::Modify => {
|
||||
if *idx == cur.idx {
|
||||
ListEditorViewSegment::Modify(self.data.get(idx)?)
|
||||
if *idx == cur {
|
||||
ListEditorViewSegment::Modify(self.data.get(&idx)?)
|
||||
} else {
|
||||
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||
ListEditorViewSegment::View(self.data.get(&idx)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ListEditorViewSegment::View(self.data.get(idx)?)
|
||||
ListEditorViewSegment::View(self.data.get(&idx)?)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -620,14 +599,14 @@ impl SequenceView for ListEditorView {
|
|||
|
||||
impl ListEditorView {
|
||||
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>>>,
|
||||
out_port: InnerViewPort<dyn SequenceView<Item = ListEditorViewSegment>>
|
||||
) -> Arc<RwLock<Self>> {
|
||||
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
|
||||
let proj = Arc::new(RwLock::new(
|
||||
ListEditorView {
|
||||
cur_cursor: None,
|
||||
cur_cursor: ListCursor::default(),
|
||||
cursor: proj_helper.new_singleton_arg(
|
||||
0,
|
||||
cursor_port,
|
||||
|
@ -635,45 +614,7 @@ impl ListEditorView {
|
|||
let old_cursor = s.cur_cursor;
|
||||
let new_cursor = s.cursor.get();
|
||||
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(
|
||||
0 ..= s.data.len().unwrap_or(0)+1
|
||||
);
|
||||
|
@ -682,10 +623,10 @@ impl ListEditorView {
|
|||
1,
|
||||
data_port,
|
||||
|s: &mut Self, idx| {
|
||||
if let Some(cur) = s.cur_cursor {
|
||||
match cur.mode {
|
||||
if let Some(cur_idx) = s.cur_cursor.idx {
|
||||
match s.cur_cursor.mode {
|
||||
ListCursorMode::Insert => {
|
||||
if *idx < cur.idx {
|
||||
if *idx < cur_idx {
|
||||
s.cast.notify(idx);
|
||||
} else {
|
||||
s.cast.notify(&(*idx + 1));
|
||||
|
@ -800,7 +741,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|
|||
let cursor_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 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>>> {
|
||||
if let Some(cur) = self.cursor.get() {
|
||||
if cur.idx < self.data.len() {
|
||||
Some(self.data.get(cur.idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let Some(idx) = self.cursor.get().idx {
|
||||
Some(self.data.get(idx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn set_idx(&mut self, idx: isize) {
|
||||
let mode =
|
||||
if let Some(c) = self.cursor.get() {
|
||||
c.mode
|
||||
} else {
|
||||
ListCursorMode::Insert
|
||||
};
|
||||
let cur = self.cursor.get();
|
||||
let mode = cur.mode;
|
||||
|
||||
if idx < 0 {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor {
|
||||
mode,
|
||||
idx: (self.data.len() as isize + idx) as usize
|
||||
}));
|
||||
idx: Some((self.data.len() as isize + idx) as usize)
|
||||
});
|
||||
} else {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
self.cursor.set(ListCursor {
|
||||
mode,
|
||||
idx: idx as usize
|
||||
}));
|
||||
idx: Some(idx as usize)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn set_mode(&mut self, mode: ListCursorMode) {
|
||||
if let Some(old_cur) = self.cursor.get() {
|
||||
let l = self.data.len();
|
||||
if old_cur.idx < l {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode,
|
||||
idx: old_cur.idx
|
||||
}));
|
||||
} else {
|
||||
self.cursor.set(Some(ListCursor {
|
||||
mode: ListCursorMode::Select,
|
||||
idx: l-1
|
||||
}));
|
||||
let mut cur = self.cursor.get();
|
||||
|
||||
if cur.mode == ListCursorMode::Insert &&
|
||||
mode != ListCursorMode::Insert
|
||||
{
|
||||
if let Some(idx) = cur.idx {
|
||||
if idx == self.data.len() && idx > 0 {
|
||||
cur.idx = Some(idx-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur.mode = mode;
|
||||
self.cursor.set(cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,31 @@ pub enum TreeNavResult {
|
|||
Continue,
|
||||
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)]
|
||||
pub struct TreeCursor {
|
||||
pub leaf_mode: ListCursorMode,
|
||||
pub tree_addr: Vec<usize>
|
||||
}
|
||||
|
||||
impl Default for TreeCursor {
|
||||
fn default() -> Self {
|
||||
TreeCursor {
|
||||
leaf_mode: ListCursorMode::Select,
|
||||
tree_addr: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TreeNav {
|
||||
fn up(&mut self) -> TreeNavResult {
|
||||
TreeNavResult::Exit
|
||||
|
@ -38,12 +56,12 @@ pub trait TreeNav {
|
|||
TreeNavResult::Exit
|
||||
}
|
||||
|
||||
fn goto(&mut self, new_cursor: Option<TreeCursor>) -> TreeNavResult {
|
||||
fn goto(&mut self, new_cursor: TreeCursor) -> TreeNavResult {
|
||||
TreeNavResult::Exit
|
||||
}
|
||||
|
||||
fn get_cursor(&self) -> Option<TreeCursor> {
|
||||
None
|
||||
fn get_cursor(&self) -> TreeCursor {
|
||||
TreeCursor::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ use{
|
|||
TerminalView,
|
||||
TerminalEditor},
|
||||
string_editor::{CharEditor},
|
||||
tree_nav::{TreeNav, TreeNavResult, TerminalTreeEditor},
|
||||
tree_nav::{TreeNav, TreeNavResult, TreeCursor, TerminalTreeEditor},
|
||||
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, 20)));
|
||||
|
||||
let monstera_port = monstera::make_monstera();
|
||||
compositor.write().unwrap().push(monstera_port.clone());
|
||||
compositor.write().unwrap().push(monstera_port.offset(Vector2::new(83,0)));
|
||||
//let monstera_port = monstera::make_monstera();
|
||||
//compositor.write().unwrap().push(monstera_port.clone());
|
||||
//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);
|
||||
|
||||
te.goto(
|
||||
TreeCursor {
|
||||
leaf_mode: ListCursorMode::Insert,
|
||||
tree_addr: vec![ 0 ]
|
||||
}
|
||||
);
|
||||
|
||||
compositor.write().unwrap().push(
|
||||
te.get_term_view()
|
||||
.offset(cgmath::Vector2::new(40,y))
|
||||
|
@ -255,13 +262,28 @@ write::
|
|||
*/
|
||||
},
|
||||
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();
|
||||
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))));
|
||||
for x in cur.tree_addr {
|
||||
for c in format!("{}", x).chars() {
|
||||
|
|
Loading…
Reference in a new issue