From f88f4971afe07a58ae3500a606d5ebcda8cb513c Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Tue, 21 Jan 2025 20:03:49 +0100 Subject: [PATCH] list segments: cache length of segment-list in cur_len --- lib-nested-core/src/editors/list/segment.rs | 88 +++++++++++++++------ 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/lib-nested-core/src/editors/list/segment.rs b/lib-nested-core/src/editors/list/segment.rs index 0245daf..3de3cc4 100644 --- a/lib-nested-core/src/editors/list/segment.rs +++ b/lib-nested-core/src/editors/list/segment.rs @@ -26,12 +26,11 @@ pub enum ListSegment { } } -/* todo: switch to ListView instead of SequenceView - */ pub struct ListSegments { data: Arc>, cursor: Arc>, + cur_len: usize, cur_cursor: ListCursor, port: ViewPort>, @@ -45,13 +44,7 @@ impl View for ListSegments { impl ListView for ListSegments { fn len(&self) -> Option { - let l = self.data.len()?; - match self.cur_cursor.mode { - ListCursorMode::Insert => { - Some(l + if self.cur_cursor.idx.is_some() { 1 } else { 0 }) - } - _ => Some(l), - } + Some(self.cur_len) } fn get(&self, idx: &usize) -> Option { @@ -96,23 +89,61 @@ impl ListSegments { ) -> Arc> { let out_port = ViewPort::new(); let mut proj_helper = ProjectionHelper::new(out_port.update_hooks.clone()); - let proj = Arc::new(RwLock::new(ListSegments { - cur_cursor: cursor_port.get_view().get(), - port: out_port.clone(), + let cur_cursor = cursor_port.get_view().get(); + let mut cur_len = data_port.get_view().unwrap().len().unwrap(); + + if cur_cursor.mode == ListCursorMode::Insert { + cur_len += 1; + } + + let proj = Arc::new(RwLock::new(ListSegments { + cur_cursor, + cur_len, + + port: out_port.clone(), 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; - if old_cursor.mode == ListCursorMode::Insert { - if let Some(idx) = old_cursor.idx { - s.cast.notify(&ListDiff::Remove(idx as usize)); + if let Some(cur_idx) = old_cursor.idx { + match old_cursor.mode { + ListCursorMode::Insert => { + eprintln!("segments: notify cursor cur len = {}", s.cur_len); + s.cur_len -= 1; + s.cast.notify(&ListDiff::Remove(cur_idx as usize)); } - } - if new_cursor.mode == ListCursorMode::Insert { - if let Some(idx) = new_cursor.idx { - s.cast.notify(&ListDiff::Insert { idx: idx as usize, val: ListSegment::InsertCursor }); + ListCursorMode::Select => { + s.cast.notify(&ListDiff::Update{ + idx: cur_idx as usize, + val: ListSegment::Item { + editor: s.data.get(&(cur_idx as usize)).unwrap(), + cur_dist: 0, + } + }) + } + } + }; + + if let Some(cur_idx) = new_cursor.idx { + match new_cursor.mode { + ListCursorMode::Insert => { + s.cur_len += 1; + s.cast.notify(&ListDiff::Insert { + idx: cur_idx as usize, + val: ListSegment::InsertCursor + }); + } + ListCursorMode::Select => { + s.cast.notify(&ListDiff::Update{ + idx: cur_idx as usize, + val: ListSegment::Item { + editor: s.data.get(&(cur_idx as usize)).unwrap(), + cur_dist: 0, + } + }) + } } } }), @@ -121,8 +152,8 @@ impl ListSegments { let mut target_idx = match diff { ListDiff::Clear => 0, ListDiff::Remove(idx) => *idx, - ListDiff::Insert { idx, val } => *idx, - ListDiff::Update { idx, val } => *idx + ListDiff::Insert { idx, val:_ } => *idx, + ListDiff::Update { idx, val:_ } => *idx }; let mut cur_dist = 0; @@ -138,16 +169,23 @@ impl ListSegments { match diff { ListDiff::Clear => { + s.cur_len = 0; s.cast.notify(&ListDiff::Clear); - if s.cur_cursor.mode == ListCursorMode::Insert { + if s.cur_cursor.mode == ListCursorMode::Insert + && s.cur_cursor.idx.is_some() + { + s.cur_cursor.idx = Some(0); + s.cur_len += 1; s.cast.notify(&ListDiff::Insert { idx: 0, val: ListSegment::InsertCursor }); } } - ListDiff::Remove(idx) => { + ListDiff::Remove(_) => { + s.cur_len -= 1; s.cast.notify(&ListDiff::Remove(target_idx)); } - ListDiff::Insert { idx, val } => { + ListDiff::Insert { idx:_, val } => { + s.cur_len += 1; s.cast.notify(&ListDiff::Insert { idx: target_idx, val: ListSegment::Item { @@ -156,7 +194,7 @@ impl ListSegments { } }); } - ListDiff::Update { idx, val } => { + ListDiff::Update { idx:_, val } => { s.cast.notify(&ListDiff::Update { idx: target_idx, val: ListSegment::Item {