lib-nested/src/string_editor.rs

150 lines
4.1 KiB
Rust
Raw Normal View History

2020-12-14 19:36:21 +01:00
use {
2021-01-06 21:35:46 +01:00
std::{
ops::Range,
sync::{Arc, RwLock},
},
cgmath::Point2,
2020-12-14 19:36:21 +01:00
crate::{
2021-01-06 21:35:46 +01:00
core::{
View,
Observer,
ObserverExt,
ObserverBroadcast,
ViewPort,
InnerViewPort,
OuterViewPort
},
sequence::SequenceView,
index::{ImplIndexView},
grid::{GridView},
terminal::{TerminalAtom, TerminalStyle, TerminalView},
//vec_buffer::VecBuffer
2020-12-14 19:36:21 +01:00
}
};
2021-01-06 21:35:46 +01:00
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
2020-12-14 19:36:21 +01:00
pub struct StringEditorState {
cursor: usize,
data: Arc<RwLock<Vec<char>>>
}
2021-01-06 21:35:46 +01:00
impl ImplIndexView for StringEditorState {
type Key = Point2<i16>;
type Value = Option<TerminalAtom>;
2020-12-14 19:36:21 +01:00
2021-01-06 21:35:46 +01:00
fn get(&self, pos: &Point2<i16>) -> Option<TerminalAtom> {
let data = self.data.read().unwrap();
2020-12-14 19:36:21 +01:00
2021-01-06 21:35:46 +01:00
if pos.y == 0 {
2020-12-14 19:36:21 +01:00
if pos.x < data.len() as i16 + 3 {
let i = pos.x as usize;
return Some(
if i == 0 {
TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130)))
2021-01-06 21:35:46 +01:00
} else if i-1 == self.cursor {
2020-12-14 19:36:21 +01:00
TerminalAtom::new('|', TerminalStyle::fg_color((180,200,130)).add(TerminalStyle::bold(true)))
} else if i-1 == data.len()+1 {
TerminalAtom::new('"', TerminalStyle::fg_color((180,200,130)))
} else {
TerminalAtom::new(
2021-01-06 21:35:46 +01:00
data.get(i as usize - if i <= self.cursor { 1 } else { 2 }).unwrap().clone(),
2020-12-14 19:36:21 +01:00
TerminalStyle::fg_color((80,150,80))
)
}
)
}
}
None
2021-01-06 21:35:46 +01:00
}
fn range(&self) -> Option<Range<Point2<i16>>> {
Some(
Point2::new(0, 0)
.. Point2::new(self.data.read().unwrap().len() as i16 + 3, 1)
)
2020-12-14 19:36:21 +01:00
}
}
pub struct StringEditor {
state: Arc<RwLock<StringEditorState>>,
2021-01-06 21:35:46 +01:00
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>
2020-12-14 19:36:21 +01:00
}
impl StringEditor {
pub fn new(
2021-01-06 21:35:46 +01:00
port: InnerViewPort<dyn TerminalView>
2020-12-14 19:36:21 +01:00
) -> Self {
let state = Arc::new(RwLock::new(StringEditorState{
2021-01-06 21:35:46 +01:00
cursor: 7,
data: Arc::new(RwLock::new("edit me".chars().collect()))
2020-12-14 19:36:21 +01:00
}));
2021-01-06 21:35:46 +01:00
let cast = port.set_view(Some(state.clone()));
2020-12-14 19:36:21 +01:00
StringEditor {
state,
2021-01-06 21:35:46 +01:00
cast
2020-12-14 19:36:21 +01:00
}
}
pub fn next(&mut self) {
let cur = self.state.read().unwrap().cursor;
self.goto(cur + 1);
}
pub fn prev(&mut self) {
let cur = self.state.read().unwrap().cursor;
if cur > 0 {
self.goto(cur - 1);
}
}
pub fn goto_end(&mut self) {
let l = self.state.read().unwrap().data.read().unwrap().len();
self.goto(l);
}
pub fn goto(&mut self, mut new_idx: usize) {
let old_idx = {
let mut state = self.state.write().unwrap();
let old_idx = state.cursor.clone();
let len = state.data.read().unwrap().len();
new_idx = std::cmp::min(new_idx, len);
state.cursor = new_idx;
old_idx
};
2021-01-06 21:35:46 +01:00
self.cast.notify_each(
2020-12-14 19:36:21 +01:00
(std::cmp::min(old_idx, new_idx) ..= std::cmp::max(old_idx, new_idx))
2021-01-06 21:35:46 +01:00
.map(|idx| Point2::new(1+idx as i16, 0))
2020-12-14 19:36:21 +01:00
);
}
pub fn insert(&mut self, c: char) {
2021-01-06 21:35:46 +01:00
self.cast.notify_each({
2020-12-14 19:36:21 +01:00
let mut state = self.state.write().unwrap();
let mut data = state.data.write().unwrap();
data.insert(state.cursor, c);
(state.cursor .. data.len()+2)
2021-01-06 21:35:46 +01:00
}.map(|idx| Point2::new(1+idx as i16, 0)));
2020-12-14 19:36:21 +01:00
self.next();
}
pub fn delete(&mut self) {
2021-01-06 21:35:46 +01:00
self.cast.notify_each({
2020-12-14 19:36:21 +01:00
let mut state = self.state.write().unwrap();
let mut data = state.data.write().unwrap();
if state.cursor < data.len() {
data.remove(state.cursor);
}
(state.cursor .. data.len()+3)
2021-01-06 21:35:46 +01:00
}.map(|idx| Point2::new(1+idx as i16, 0)));
2020-12-14 19:36:21 +01:00
}
}