From 11eb30bd5b4417d4d377938883b96418933b70af Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Sat, 28 Aug 2021 03:08:41 +0200 Subject: [PATCH] list editor cleanup & fix nesting --- nested/src/list/editor.rs | 385 ++++++++++++--------------------- nested/src/list/editor_view.rs | 142 ++++++++++++ nested/src/list/mod.rs | 1 + nested/src/list/sexpr.rs | 3 + 4 files changed, 283 insertions(+), 248 deletions(-) create mode 100644 nested/src/list/editor_view.rs diff --git a/nested/src/list/editor.rs b/nested/src/list/editor.rs index 3413a17..9723b77 100644 --- a/nested/src/list/editor.rs +++ b/nested/src/list/editor.rs @@ -31,23 +31,36 @@ use { make_label }, leveled_term_view::LeveledTermView, - list::{SExprView, ListDecoration, ListCursor, ListCursorMode}, + list::{SExprView, ListDecoration, ListCursor, ListCursorMode, editor_view::{ListEditorView, ListEditorViewSegment}}, tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor} } }; +#[derive(Clone, Copy)] +pub enum ListEditorStyle { + HorizontalSexpr, + VerticalSexpr, + Path, + String, + Clist, + Hex, + Plain +} + pub struct ListEditor where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, FnMakeItemEditor: Fn() -> Arc> { cursor: SingletonBuffer, data: VecBuffer>>, - data_sequence_port: OuterViewPort>>>, - make_item_editor: FnMakeItemEditor, - level: usize, - segment_seq: OuterViewPort>, - terminal_view: OuterViewPort + cursor_port: ViewPort>, + data_port: ViewPort>>>>, + + make_item_editor: FnMakeItemEditor, + + style: ListEditorStyle, + level: usize, } impl TreeNav for ListEditor @@ -150,40 +163,32 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, let ce = self.data.get_mut(i); let mut cur_edit = ce.write().unwrap(); let cur_mode = cur_edit.get_cursor().leaf_mode; - + let depth = cur_edit.get_cursor().tree_addr.len(); match cur_edit.goto_end() { TreeNavResult::Continue => { TreeNavResult::Continue } TreeNavResult::Exit => { + drop(cur_edit); + self.up(); + if let Some(i) = cur.idx { if i+1 < self.data.len() { - cur_edit.up(); - drop(cur_edit); - self.nexd(); - self.set_mode(ListCursorMode::Modify); + self.set_leaf_mode(cur_mode); - let ne = self.get_item().unwrap(); - let mut nxd_edit = ne.write().unwrap(); + for x in 1 .. depth { + self.dn(); + self.goto_home(); + } - nxd_edit.goto( - TreeCursor { - leaf_mode: cur_mode, - tree_addr: vec![] - } - ); - nxd_edit.goto_end(); + self.dn(); + self.goto_end(); - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit + return TreeNavResult::Continue; } - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit } + TreeNavResult::Exit } } } @@ -216,37 +221,31 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, let ce = self.get_item().unwrap(); let mut cur_edit = ce.write().unwrap(); let cur_mode = cur_edit.get_cursor().leaf_mode; + let depth = cur_edit.get_cursor().tree_addr.len(); match cur_edit.goto_home() { TreeNavResult::Exit => { + drop(cur_edit); + self.up(); + if let Some(i) = cur.idx { if i > 0 { - cur_edit.up(); - drop(cur_edit); - + self.set_mode(ListCursorMode::Select); self.pxev(); - self.set_mode(ListCursorMode::Modify); - let pe = self.get_item().unwrap(); - let mut pxv_edit = pe.write().unwrap(); + for x in 1 .. depth { + self.dn(); + self.goto_end(); + } - pxv_edit.goto( - TreeCursor { - leaf_mode: cur_mode, - tree_addr: vec![] - } - ); - pxv_edit.goto_home(); - - TreeNavResult::Continue - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit + self.set_leaf_mode(cur_mode); + self.dn(); + self.goto_home(); + return TreeNavResult::Continue; } - } else { - self.cursor.set(ListCursor::default()); - TreeNavResult::Exit } + + TreeNavResult::Exit } TreeNavResult::Continue => TreeNavResult::Continue } @@ -291,7 +290,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, self.data.get_mut(i).write().unwrap().goto( TreeCursor { leaf_mode: cur.mode, - tree_addr: vec![ 0 ] + tree_addr: vec![] } ); } @@ -322,29 +321,29 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, ListCursorMode::Modify => { let ce = self.get_item().unwrap(); let mut cur_edit = ce.write().unwrap(); + let cur_mode = cur_edit.get_cursor().leaf_mode; + let depth = cur_edit.get_cursor().tree_addr.len(); match cur_edit.pxev() { TreeNavResult::Exit => { drop(cur_edit); - if i > 0 { - self.up(); - self.pxev(); - self.set_mode(ListCursorMode::Modify); + self.up(); - 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(); + if i > 0 { + self.pxev(); + + for x in 1 .. depth { + self.dn(); + self.goto_end(); + } + + self.set_leaf_mode(cur_mode); + self.dn(); + self.goto_end(); TreeNavResult::Continue } else { - self.cursor.set(ListCursor::default()); TreeNavResult::Exit } }, @@ -384,21 +383,27 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, ListCursorMode::Modify => { let ce = self.data.get(i); let mut cur_edit = ce.write().unwrap(); + + let depth = cur_edit.get_cursor().tree_addr.len(); let cur_mode = cur_edit.get_cursor().leaf_mode; match cur_edit.nexd() { TreeNavResult::Exit => { - if i+1 < self.data.len() { - cur_edit.up(); - drop(cur_edit); - drop(ce); + drop(cur_edit); + drop(ce); + self.up(); - self.set_mode(cur_mode); + if i+1 < self.data.len() { self.nexd(); - self.dn(); + + for x in 0 .. depth { + self.dn(); + self.goto_home(); + } + + self.set_leaf_mode(cur_mode); TreeNavResult::Continue } else { - self.cursor.set(ListCursor::default()); TreeNavResult::Exit } } @@ -417,7 +422,15 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, FnMakeItemEditor: Fn() -> Arc> { fn get_term_view(&self) -> OuterViewPort { - self.terminal_view.clone() + match self.style { + ListEditorStyle::HorizontalSexpr => self.horizontal_sexpr_view(), + ListEditorStyle::VerticalSexpr => self.vertical_sexpr_view(), + ListEditorStyle::Path => self.path_view(), + ListEditorStyle::String => self.string_view(), + ListEditorStyle::Clist => self.clist_view(), + ListEditorStyle::Hex => self.hex_view(), + ListEditorStyle::Plain => self.plain_view() + } } fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { @@ -453,6 +466,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, let new_edit = (self.make_item_editor)(); self.data.insert(idx, new_edit.clone()); self.dn(); + self.goto_home(); match new_edit.write().unwrap().handle_terminal_event(event) { TerminalEditorResult::Exit => { @@ -495,35 +509,35 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, ListCursorMode::Modify => { let mut ce = self.data.get_mut(idx); let mut cur_edit = ce.write().unwrap(); - match event { - TerminalEvent::Input(Event::Key(Key::Char(' '))) => { - // split.. + + match cur_edit.handle_terminal_event(event) { + TerminalEditorResult::Exit => { cur_edit.up(); drop(cur_edit); - self.cursor.set(ListCursor { - mode: ListCursorMode::Insert, - idx: Some(idx+1) - }); - TerminalEditorResult::Continue - } - TerminalEvent::Input(Event::Key(Key::Backspace)) => { - match cur_edit.handle_terminal_event(event) { - TerminalEditorResult::Exit => { - drop(cur_edit); - drop(ce); + + match event { + TerminalEvent::Input(Event::Key(Key::Char(' '))) => { + // split.. + self.cursor.set(ListCursor { + mode: ListCursorMode::Insert, + idx: Some(idx+1) + }); + } + TerminalEvent::Input(Event::Key(Key::Backspace)) => { self.cursor.set(ListCursor { mode: ListCursorMode::Insert, idx: Some(idx) }); + self.data.remove(idx); // todo: join instead of remove } - TerminalEditorResult::Continue => { - } + _ => {} } - TerminalEditorResult::Continue - } - _ => cur_edit.handle_terminal_event(event) + }, + TerminalEditorResult::Continue => {} } + + TerminalEditorResult::Continue } } } else { @@ -532,142 +546,18 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, } } -enum ListEditorViewSegment { - InsertCursor, - View(OuterViewPort), - Select(OuterViewPort), - Modify(OuterViewPort) -} - -struct ListEditorView { - cursor: Arc>, - data: Arc>>, - cur_cursor: ListCursor, - - cast: Arc>>>, - proj_helper: ProjectionHelper -} - -impl View for ListEditorView { - type Msg = usize; -} - -impl SequenceView for ListEditorView { - type Item = ListEditorViewSegment; - - fn len(&self) -> Option { - match self.cursor.get().mode { - ListCursorMode::Insert => Some(self.data.len()? + 1), - _ => self.data.len() - } - } - - fn get(&self, idx: &usize) -> Option { - Some( - if let Some(cur) = self.cur_cursor.idx { - match self.cur_cursor.mode { - ListCursorMode::Select => { - if *idx == cur { - ListEditorViewSegment::Select(self.data.get(&idx)?) - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - } - } - ListCursorMode::Insert => { - 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 { - ListEditorViewSegment::Modify(self.data.get(&idx)?) - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - } - } - } - } else { - ListEditorViewSegment::View(self.data.get(&idx)?) - } - ) - } -} - -impl ListEditorView { - fn new( - cursor_port: OuterViewPort>, - data_port: OuterViewPort>>, - out_port: InnerViewPort> - ) -> Arc> { - let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); - let proj = Arc::new(RwLock::new( - ListEditorView { - cur_cursor: ListCursor::default(), - cursor: proj_helper.new_singleton_arg( - 0, - cursor_port, - |s: &mut Self, _msg| { - let old_cursor = s.cur_cursor; - let new_cursor = s.cursor.get(); - s.cur_cursor = new_cursor; - - s.cast.notify_each( - 0 ..= s.data.len().unwrap_or(0)+1 - ); - }), - data: proj_helper.new_sequence_arg( - 1, - data_port, - |s: &mut Self, idx| { - if let Some(cur_idx) = s.cur_cursor.idx { - match s.cur_cursor.mode { - ListCursorMode::Insert => { - if *idx < cur_idx { - s.cast.notify(idx); - } else { - s.cast.notify(&(*idx + 1)); - } - }, - _ => { - s.cast.notify(idx); - } - } - } else { - s.cast.notify(idx); - } - }), - cast: out_port.get_broadcast(), - proj_helper - } - )); - - proj.write().unwrap().proj_helper.set_proj(&proj); - out_port.set_view(Some(proj.clone())); - - proj - } -} - -pub enum ListEditorStyle { - HorizontalSexpr, - VerticalSexpr, - Path, - String, - Clist, - Hex, - Plain -} - impl ListEditor where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, FnMakeItemEditor: Fn() -> Arc> { pub fn get_seg_seq_view(&self) -> OuterViewPort>> { - self.segment_seq + let segment_view_port = ViewPort::>::new(); + ListEditorView::new( + self.cursor_port.outer(), + self.data_port.outer().to_sequence().map(|ed| ed.read().unwrap().get_term_view()), + segment_view_port.inner() + ); + segment_view_port.into_outer() .map( |segment| match segment { ListEditorViewSegment::InsertCursor => @@ -683,12 +573,13 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, |_pt, atom| atom.add_style_front(TerminalStyle::bg_color((90,60,200))) ), - ListEditorViewSegment::Modify(sub_view) => + ListEditorViewSegment::Modify(sub_view) => { sub_view.map_item( |_pt, atom| atom.add_style_back(TerminalStyle::bg_color((0,0,0))) .add_style_back(TerminalStyle::bold(true)) - ), + ) + }, ListEditorViewSegment::View(sub_view) => sub_view.clone() } @@ -740,46 +631,33 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self { let cursor_port = ViewPort::new(); let data_port = ViewPort::new(); - let mut cursor = SingletonBuffer::new(ListCursor::default(), cursor_port.inner()); let mut data = VecBuffer::>>::new(data_port.inner()); - let data_sequence_port = data_port.into_outer().to_sequence(); - - let segment_view_port = ViewPort::>::new(); - let segment_view = ListEditorView::new( - cursor_port.outer(), - data_sequence_port.map(|ed| ed.read().unwrap().get_term_view()), - segment_view_port.inner() - ); - let mut le = ListEditor { data, - data_sequence_port, + data_port, cursor, + cursor_port, + + style, make_item_editor, - level: 0, - segment_seq: segment_view_port.outer(), - terminal_view: make_label("lol"), + level: 0 }; le.set_style(style); le } pub fn set_style(&mut self, style: ListEditorStyle) { - self.terminal_view = match style { - ListEditorStyle::HorizontalSexpr => self.horizontal_sexpr_view(), - ListEditorStyle::VerticalSexpr => self.vertical_sexpr_view(), - ListEditorStyle::Path => self.path_view(), - ListEditorStyle::String => self.string_view(), - ListEditorStyle::Clist => self.clist_view(), - ListEditorStyle::Hex => self.hex_view(), - ListEditorStyle::Plain => self.plain_view() - } + self.style = style; } pub fn get_data_port(&self) -> OuterViewPort>>> { - self.data_sequence_port.clone() + self.data_port.outer().to_sequence() + } + + pub fn get_list_cursor_port(&self) -> OuterViewPort> { + self.cursor_port.outer() } fn get_item(&self) -> Option>> { @@ -806,7 +684,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, }); } } - + fn set_mode(&mut self, mode: ListCursorMode) { let mut cur = self.cursor.get(); @@ -825,3 +703,14 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static, } } +impl ListEditor +where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static, + FnMakeItemEditor: Fn() -> Arc> +{ + fn set_leaf_mode(&mut self, mode: ListCursorMode) { + let mut c = self.get_cursor(); + c.leaf_mode = mode; + self.goto(c); + } +} + diff --git a/nested/src/list/editor_view.rs b/nested/src/list/editor_view.rs new file mode 100644 index 0000000..3ca2579 --- /dev/null +++ b/nested/src/list/editor_view.rs @@ -0,0 +1,142 @@ +use { + std::sync::Arc, + std::sync::RwLock, + crate::{ + core::{ + View, + InnerViewPort, + OuterViewPort, + Observer, + ObserverExt, + ObserverBroadcast + }, + projection::ProjectionHelper, + + singleton::SingletonView, + sequence::SequenceView, + terminal::TerminalView, + + list::{ListCursor, ListCursorMode} + } +}; + +pub enum ListEditorViewSegment { + InsertCursor, + View(OuterViewPort), + Select(OuterViewPort), + Modify(OuterViewPort) +} + +pub struct ListEditorView { + cursor: Arc>, + data: Arc>>, + cur_cursor: ListCursor, + + cast: Arc>>>, + proj_helper: ProjectionHelper +} + +impl View for ListEditorView { + type Msg = usize; +} + +impl SequenceView for ListEditorView { + type Item = ListEditorViewSegment; + + fn len(&self) -> Option { + match self.cursor.get().mode { + ListCursorMode::Insert => Some(self.data.len()? + if self.cur_cursor.idx.is_some() { 1 } else { 0 }), + _ => self.data.len() + } + } + + fn get(&self, idx: &usize) -> Option { + Some( + if let Some(cur) = self.cur_cursor.idx { + match self.cur_cursor.mode { + ListCursorMode::Select => { + if *idx == cur { + ListEditorViewSegment::Select(self.data.get(&idx)?) + } else { + ListEditorViewSegment::View(self.data.get(&idx)?) + } + } + ListCursorMode::Insert => { + 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 { + ListEditorViewSegment::Modify(self.data.get(&idx)?) + } else { + ListEditorViewSegment::View(self.data.get(&idx)?) + } + } + } + } else { + ListEditorViewSegment::View(self.data.get(&idx)?) + } + ) + } +} + +impl ListEditorView { + pub fn new( + cursor_port: OuterViewPort>, + data_port: OuterViewPort>>, + out_port: InnerViewPort> + ) -> Arc> { + let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone()); + let proj = Arc::new(RwLock::new( + ListEditorView { + cur_cursor: ListCursor::default(), + cursor: proj_helper.new_singleton_arg( + 0, + cursor_port, + |s: &mut Self, _msg| { + let old_cursor = s.cur_cursor; + let new_cursor = s.cursor.get(); + s.cur_cursor = new_cursor; + + s.cast.notify_each( + 0 ..= s.data.len().unwrap_or(0)+1 + ); + }), + data: proj_helper.new_sequence_arg( + 1, + data_port, + |s: &mut Self, idx| { + if let Some(cur_idx) = s.cur_cursor.idx { + match s.cur_cursor.mode { + ListCursorMode::Insert => { + if *idx < cur_idx { + s.cast.notify(idx); + } else { + s.cast.notify(&(*idx + 1)); + } + }, + _ => { + s.cast.notify(idx); + } + } + } else { + s.cast.notify(idx); + } + }), + cast: out_port.get_broadcast(), + proj_helper + } + )); + + proj.write().unwrap().proj_helper.set_proj(&proj); + out_port.set_view(Some(proj.clone())); + + proj + } +} + diff --git a/nested/src/list/mod.rs b/nested/src/list/mod.rs index bb03bae..52e9d3c 100644 --- a/nested/src/list/mod.rs +++ b/nested/src/list/mod.rs @@ -2,6 +2,7 @@ pub mod sexpr; pub mod cursor; pub mod editor; +pub mod editor_view; pub use sexpr::{SExprView, ListDecoration}; pub use cursor::{ListCursorMode, ListCursor}; diff --git a/nested/src/list/sexpr.rs b/nested/src/list/sexpr.rs index 73c6d35..ec4f09f 100644 --- a/nested/src/list/sexpr.rs +++ b/nested/src/list/sexpr.rs @@ -157,6 +157,9 @@ impl IndexView> for VerticalSexprDecorator { } fn get(&self, pt: &Point2) -> Option { + if pt.y < 0 { + return None; + } let item_idx = pt.y as usize; let list_style = self.list_style.clone(); let item_style = self.item_style.clone();