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)]
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
}
}
}

View file

@ -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 => {
}
@ -544,7 +527,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
}
}
} else {
TerminalEditorResult::Continue
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);
}
}

View file

@ -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()
}
}

View file

@ -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() {