list editor cleanup & fix nesting

This commit is contained in:
Michael Sippel 2021-08-28 03:08:41 +02:00
parent fb5ae53e88
commit 11eb30bd5b
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 283 additions and 248 deletions

View file

@ -31,23 +31,36 @@ use {
make_label make_label
}, },
leveled_term_view::LeveledTermView, leveled_term_view::LeveledTermView,
list::{SExprView, ListDecoration, ListCursor, ListCursorMode}, list::{SExprView, ListDecoration, ListCursor, ListCursorMode, editor_view::{ListEditorView, ListEditorViewSegment}},
tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor} tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor}
} }
}; };
#[derive(Clone, Copy)]
pub enum ListEditorStyle {
HorizontalSexpr,
VerticalSexpr,
Path,
String,
Clist,
Hex,
Plain
}
pub struct ListEditor<ItemEditor, FnMakeItemEditor> 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<ListCursor>, cursor: SingletonBuffer<ListCursor>,
data: VecBuffer<Arc<RwLock<ItemEditor>>>, data: VecBuffer<Arc<RwLock<ItemEditor>>>,
data_sequence_port: OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>>,
make_item_editor: FnMakeItemEditor,
level: usize,
segment_seq: OuterViewPort<dyn SequenceView<Item = ListEditorViewSegment>>,
terminal_view: OuterViewPort<dyn TerminalView> cursor_port: ViewPort<dyn SingletonView<Item = ListCursor>>,
data_port: ViewPort<RwLock<Vec<Arc<RwLock<ItemEditor>>>>>,
make_item_editor: FnMakeItemEditor,
style: ListEditorStyle,
level: usize,
} }
impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> TreeNav for ListEditor<ItemEditor, FnMakeItemEditor>
@ -150,40 +163,32 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
let ce = self.data.get_mut(i); let ce = self.data.get_mut(i);
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
let cur_mode = cur_edit.get_cursor().leaf_mode; let cur_mode = cur_edit.get_cursor().leaf_mode;
let depth = cur_edit.get_cursor().tree_addr.len();
match cur_edit.goto_end() { match cur_edit.goto_end() {
TreeNavResult::Continue => { TreeNavResult::Continue => {
TreeNavResult::Continue TreeNavResult::Continue
} }
TreeNavResult::Exit => { TreeNavResult::Exit => {
drop(cur_edit);
self.up();
if let Some(i) = cur.idx { if let Some(i) = cur.idx {
if i+1 < self.data.len() { if i+1 < self.data.len() {
cur_edit.up();
drop(cur_edit);
self.nexd(); self.nexd();
self.set_mode(ListCursorMode::Modify); self.set_leaf_mode(cur_mode);
let ne = self.get_item().unwrap(); for x in 1 .. depth {
let mut nxd_edit = ne.write().unwrap(); self.dn();
self.goto_home();
}
nxd_edit.goto( self.dn();
TreeCursor { self.goto_end();
leaf_mode: cur_mode,
tree_addr: vec![]
}
);
nxd_edit.goto_end();
TreeNavResult::Continue return TreeNavResult::Continue;
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
} }
} 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 ce = self.get_item().unwrap();
let mut cur_edit = ce.write().unwrap(); let mut cur_edit = ce.write().unwrap();
let cur_mode = cur_edit.get_cursor().leaf_mode; let cur_mode = cur_edit.get_cursor().leaf_mode;
let depth = cur_edit.get_cursor().tree_addr.len();
match cur_edit.goto_home() { match cur_edit.goto_home() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
drop(cur_edit);
self.up();
if let Some(i) = cur.idx { if let Some(i) = cur.idx {
if i > 0 { if i > 0 {
cur_edit.up(); self.set_mode(ListCursorMode::Select);
drop(cur_edit);
self.pxev(); self.pxev();
self.set_mode(ListCursorMode::Modify);
let pe = self.get_item().unwrap(); for x in 1 .. depth {
let mut pxv_edit = pe.write().unwrap(); self.dn();
self.goto_end();
}
pxv_edit.goto( self.set_leaf_mode(cur_mode);
TreeCursor { self.dn();
leaf_mode: cur_mode, self.goto_home();
tree_addr: vec![] return TreeNavResult::Continue;
}
);
pxv_edit.goto_home();
TreeNavResult::Continue
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
} }
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
} }
TreeNavResult::Exit
} }
TreeNavResult::Continue => TreeNavResult::Continue TreeNavResult::Continue => TreeNavResult::Continue
} }
@ -291,7 +290,7 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
self.data.get_mut(i).write().unwrap().goto( self.data.get_mut(i).write().unwrap().goto(
TreeCursor { TreeCursor {
leaf_mode: cur.mode, leaf_mode: cur.mode,
tree_addr: vec![ 0 ] tree_addr: vec![]
} }
); );
} }
@ -322,29 +321,29 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
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 = cur_edit.get_cursor().leaf_mode; let cur_mode = cur_edit.get_cursor().leaf_mode;
let depth = cur_edit.get_cursor().tree_addr.len();
match cur_edit.pxev() { match cur_edit.pxev() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
drop(cur_edit); drop(cur_edit);
if i > 0 { self.up();
self.up();
self.pxev();
self.set_mode(ListCursorMode::Modify);
let pe = self.get_item().unwrap(); if i > 0 {
let mut pxv_edit = pe.write().unwrap(); self.pxev();
pxv_edit.goto(
TreeCursor { for x in 1 .. depth {
leaf_mode: cur_mode, self.dn();
tree_addr: vec![] self.goto_end();
} }
);
pxv_edit.goto_end(); self.set_leaf_mode(cur_mode);
self.dn();
self.goto_end();
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
}, },
@ -384,21 +383,27 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
ListCursorMode::Modify => { ListCursorMode::Modify => {
let ce = self.data.get(i); let ce = self.data.get(i);
let mut cur_edit = ce.write().unwrap(); 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; let cur_mode = cur_edit.get_cursor().leaf_mode;
match cur_edit.nexd() { match cur_edit.nexd() {
TreeNavResult::Exit => { TreeNavResult::Exit => {
if i+1 < self.data.len() { drop(cur_edit);
cur_edit.up(); drop(ce);
drop(cur_edit); self.up();
drop(ce);
self.set_mode(cur_mode); if i+1 < self.data.len() {
self.nexd(); self.nexd();
self.dn();
for x in 0 .. depth {
self.dn();
self.goto_home();
}
self.set_leaf_mode(cur_mode);
TreeNavResult::Continue TreeNavResult::Continue
} else { } else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit TreeNavResult::Exit
} }
} }
@ -417,7 +422,15 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
{ {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> { fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
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 { 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)(); let new_edit = (self.make_item_editor)();
self.data.insert(idx, new_edit.clone()); self.data.insert(idx, new_edit.clone());
self.dn(); self.dn();
self.goto_home();
match new_edit.write().unwrap().handle_terminal_event(event) { match new_edit.write().unwrap().handle_terminal_event(event) {
TerminalEditorResult::Exit => { TerminalEditorResult::Exit => {
@ -495,35 +509,35 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
ListCursorMode::Modify => { ListCursorMode::Modify => {
let mut ce = self.data.get_mut(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 {
TerminalEvent::Input(Event::Key(Key::Char(' '))) => { match cur_edit.handle_terminal_event(event) {
// split.. TerminalEditorResult::Exit => {
cur_edit.up(); cur_edit.up();
drop(cur_edit); drop(cur_edit);
self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, match event {
idx: Some(idx+1) TerminalEvent::Input(Event::Key(Key::Char(' '))) => {
}); // split..
TerminalEditorResult::Continue self.cursor.set(ListCursor {
} mode: ListCursorMode::Insert,
TerminalEvent::Input(Event::Key(Key::Backspace)) => { idx: Some(idx+1)
match cur_edit.handle_terminal_event(event) { });
TerminalEditorResult::Exit => { }
drop(cur_edit); TerminalEvent::Input(Event::Key(Key::Backspace)) => {
drop(ce);
self.cursor.set(ListCursor { self.cursor.set(ListCursor {
mode: ListCursorMode::Insert, mode: ListCursorMode::Insert,
idx: Some(idx) idx: Some(idx)
}); });
self.data.remove(idx); // todo: join instead of remove self.data.remove(idx); // todo: join instead of remove
} }
TerminalEditorResult::Continue => { _ => {}
}
} }
TerminalEditorResult::Continue },
} TerminalEditorResult::Continue => {}
_ => cur_edit.handle_terminal_event(event)
} }
TerminalEditorResult::Continue
} }
} }
} else { } else {
@ -532,142 +546,18 @@ where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
} }
} }
enum ListEditorViewSegment {
InsertCursor,
View(OuterViewPort<dyn TerminalView>),
Select(OuterViewPort<dyn TerminalView>),
Modify(OuterViewPort<dyn TerminalView>)
}
struct ListEditorView {
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
cur_cursor: ListCursor,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
proj_helper: ProjectionHelper<usize, Self>
}
impl View for ListEditorView {
type Msg = usize;
}
impl SequenceView for ListEditorView {
type Item = ListEditorViewSegment;
fn len(&self) -> Option<usize> {
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.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<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: 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<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor> impl<ItemEditor, FnMakeItemEditor> 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>>
{ {
pub fn get_seg_seq_view(&self) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> { pub fn get_seg_seq_view(&self) -> OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>> {
self.segment_seq let segment_view_port = ViewPort::<dyn SequenceView<Item = ListEditorViewSegment>>::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( .map(
|segment| match segment { |segment| match segment {
ListEditorViewSegment::InsertCursor => ListEditorViewSegment::InsertCursor =>
@ -683,12 +573,13 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
|_pt, atom| |_pt, atom|
atom.add_style_front(TerminalStyle::bg_color((90,60,200))) atom.add_style_front(TerminalStyle::bg_color((90,60,200)))
), ),
ListEditorViewSegment::Modify(sub_view) => ListEditorViewSegment::Modify(sub_view) => {
sub_view.map_item( sub_view.map_item(
|_pt, atom| |_pt, atom|
atom.add_style_back(TerminalStyle::bg_color((0,0,0))) atom.add_style_back(TerminalStyle::bg_color((0,0,0)))
.add_style_back(TerminalStyle::bold(true)) .add_style_back(TerminalStyle::bold(true))
), )
},
ListEditorViewSegment::View(sub_view) => ListEditorViewSegment::View(sub_view) =>
sub_view.clone() sub_view.clone()
} }
@ -740,46 +631,33 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self { pub fn new(make_item_editor: FnMakeItemEditor, style: ListEditorStyle) -> Self {
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(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 segment_view_port = ViewPort::<dyn SequenceView<Item = ListEditorViewSegment>>::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 { let mut le = ListEditor {
data, data,
data_sequence_port, data_port,
cursor, cursor,
cursor_port,
style,
make_item_editor, make_item_editor,
level: 0, level: 0
segment_seq: segment_view_port.outer(),
terminal_view: make_label("lol"),
}; };
le.set_style(style); le.set_style(style);
le le
} }
pub fn set_style(&mut self, style: ListEditorStyle) { pub fn set_style(&mut self, style: ListEditorStyle) {
self.terminal_view = match style { self.style = 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()
}
} }
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>> { pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = Arc<RwLock<ItemEditor>>>> {
self.data_sequence_port.clone() self.data_port.outer().to_sequence()
}
pub fn get_list_cursor_port(&self) -> OuterViewPort<dyn SingletonView<Item = ListCursor>> {
self.cursor_port.outer()
} }
fn get_item(&self) -> Option<Arc<RwLock<ItemEditor>>> { fn get_item(&self) -> Option<Arc<RwLock<ItemEditor>>> {
@ -806,7 +684,7 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
}); });
} }
} }
fn set_mode(&mut self, mode: ListCursorMode) { fn set_mode(&mut self, mode: ListCursorMode) {
let mut cur = self.cursor.get(); let mut cur = self.cursor.get();
@ -825,3 +703,14 @@ where ItemEditor: TerminalEditor + ?Sized + Send + Sync + 'static,
} }
} }
impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor>
where ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>>
{
fn set_leaf_mode(&mut self, mode: ListCursorMode) {
let mut c = self.get_cursor();
c.leaf_mode = mode;
self.goto(c);
}
}

View file

@ -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<dyn TerminalView>),
Select(OuterViewPort<dyn TerminalView>),
Modify(OuterViewPort<dyn TerminalView>)
}
pub struct ListEditorView {
cursor: Arc<dyn SingletonView<Item = ListCursor>>,
data: Arc<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
cur_cursor: ListCursor,
cast: Arc<RwLock<ObserverBroadcast<dyn SequenceView<Item = ListEditorViewSegment>>>>,
proj_helper: ProjectionHelper<usize, Self>
}
impl View for ListEditorView {
type Msg = usize;
}
impl SequenceView for ListEditorView {
type Item = ListEditorViewSegment;
fn len(&self) -> Option<usize> {
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<Self::Item> {
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<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: 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
}
}

View file

@ -2,6 +2,7 @@
pub mod sexpr; pub mod sexpr;
pub mod cursor; pub mod cursor;
pub mod editor; pub mod editor;
pub mod editor_view;
pub use sexpr::{SExprView, ListDecoration}; pub use sexpr::{SExprView, ListDecoration};
pub use cursor::{ListCursorMode, ListCursor}; pub use cursor::{ListCursorMode, ListCursor};

View file

@ -157,6 +157,9 @@ impl IndexView<Point2<i16>> for VerticalSexprDecorator {
} }
fn get(&self, pt: &Point2<i16>) -> Option<Self::Item> { fn get(&self, pt: &Point2<i16>) -> Option<Self::Item> {
if pt.y < 0 {
return None;
}
let item_idx = pt.y as usize; let item_idx = pt.y as usize;
let list_style = self.list_style.clone(); let list_style = self.list_style.clone();
let item_style = self.item_style.clone(); let item_style = self.item_style.clone();