product editor: grid layout

This commit is contained in:
Michael Sippel 2022-06-26 00:49:35 +02:00
parent d8e8f763a6
commit 55eb594521
Signed by: senvas
GPG key ID: F96CF119C34B64A6
4 changed files with 160 additions and 65 deletions

View file

@ -4,7 +4,7 @@ use {
index::{IndexArea, IndexView}, index::{IndexArea, IndexView},
}, },
std::sync::RwLock, std::sync::RwLock,
std::{collections::HashMap, hash::Hash, sync::Arc}, std::{collections::HashMap, hash::Hash, sync::Arc, ops::{Deref, DerefMut}},
}; };
pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>) pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>)
@ -36,6 +36,7 @@ where
} }
} }
#[derive(Clone)]
pub struct IndexBuffer<Key, Item> pub struct IndexBuffer<Key, Item>
where where
Key: Clone + Hash + Eq + Send + Sync + 'static, Key: Clone + Hash + Eq + Send + Sync + 'static,
@ -68,6 +69,27 @@ where
self.port.0.outer() self.port.0.outer()
} }
pub fn get(&self, key: &Key) -> Option<Item> {
self.data.read().unwrap().get(key).cloned()
}
pub fn get_mut(&mut self, key: &Key) -> MutableIndexAccess<Key, Item> {
MutableIndexAccess {
buf: self.clone(),
key: key.clone(),
val: self.get(key)
}
}
pub fn update(&mut self, key: Key, item: Option<Item>) {
if let Some(item) = item {
self.data.write().unwrap().insert(key.clone(), item);
} else {
self.data.write().unwrap().remove(&key);
}
self.port.notify(&IndexArea::Set(vec![key]));
}
pub fn insert(&mut self, key: Key, item: Item) { pub fn insert(&mut self, key: Key, item: Item) {
self.data.write().unwrap().insert(key.clone(), item); self.data.write().unwrap().insert(key.clone(), item);
self.port.notify(&IndexArea::Set(vec![key])); self.port.notify(&IndexArea::Set(vec![key]));
@ -87,3 +109,48 @@ where
self.port.notify(&IndexArea::Set(vec![key])); self.port.notify(&IndexArea::Set(vec![key]));
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct MutableIndexAccess<Key, Item>
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
buf: IndexBuffer<Key, Item>,
key: Key,
val: Option<Item>,
}
impl<Key, Item> Deref for MutableIndexAccess<Key, Item>
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
type Target = Option<Item>;
fn deref(&self) -> &Option<Item> {
&self.val
}
}
impl<Key, Item> DerefMut for MutableIndexAccess<Key, Item>
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.val
}
}
impl<Key, Item> Drop for MutableIndexAccess<Key, Item>
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
Item: Clone + Send + Sync + 'static,
{
fn drop(&mut self) {
self.buf.update(self.key.clone(), self.val.clone());
}
}

View file

@ -10,7 +10,7 @@ use {
product::editor::ProductEditor, product::editor::ProductEditor,
char_editor::CharEditor char_editor::CharEditor
}, },
cgmath::Vector2, cgmath::{Vector2, Point2},
std::sync::{Arc, RwLock}, std::sync::{Arc, RwLock},
}; };
@ -90,24 +90,44 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else if t[0] == c.type_term_from_str("( RGB )").unwrap() { } else if t[0] == c.type_term_from_str("( RGB )").unwrap() {
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_t("{ r: ") .with_t(Point2::new(0, 0), "{")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 1), "r: ")
.with_t(", g: ") .with_n(Point2::new(2, 1), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 2), "g: ")
.with_t(", b: ") .with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 3), "b: ")
.with_t(" }") .with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(Point2::new(0, 4), " }")
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> )) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() { } else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() {
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone()) Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_t("{ x: ") .with_t(Point2::new(0, 0), "{")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 1), "x: ")
.with_t(", y: ") .with_n(Point2::new(2, 1), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 2), "y: ")
.with_t(", z: ") .with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] ) .with_t(Point2::new(1, 3), "z: ")
.with_t(" }") .with_n(Point2::new(2, 3), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(Point2::new(0, 4), " }")
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( Json )").unwrap() {
Arc::new(RwLock::new(
PTYListEditor::<dyn TerminalTreeEditor + Send + Sync>::new(
Box::new({
let ctx = ctx.clone();
move || {
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_n(Point2::new(0, 0), vec![ ctx.read().unwrap().type_term_from_str("( String )").unwrap() ] )
.with_t(Point2::new(1, 0), ": ")
.with_n(Point2::new(2, 0), vec![ ctx.read().unwrap().type_term_from_str("( Json )").unwrap() ] )
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
}
}),
SeqDecorStyle::VerticalSexpr,
depth
)
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> )) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( List Term )").unwrap() { } else if t[0] == c.type_term_from_str("( List Term )").unwrap() {
@ -126,10 +146,15 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else { // else: term } else { // else: term
Arc::new(RwLock::new( Arc::new(RwLock::new(
ProductEditor::new(depth, ctx.clone()) PTYListEditor::new(
.with_n( vec![ c.type_term_from_str("( List Char )").unwrap() ] ) Box::new(|| {
.with_n( vec![ c.type_term_from_str("( List Term )").unwrap() ] ) Arc::new(RwLock::new(CharEditor::new()))
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> }),
SeqDecorStyle::DoubleQuote,
depth
)
))
} }
} }

View file

@ -8,18 +8,20 @@ use {
sequence::{SequenceView}, sequence::{SequenceView},
tree_nav::{TreeNav, TerminalTreeEditor, TreeNavResult}, tree_nav::{TreeNav, TerminalTreeEditor, TreeNavResult},
vec::{VecBuffer, MutableVecAccess}, vec::{VecBuffer, MutableVecAccess},
index::{buffer::{IndexBuffer, MutableIndexAccess}, IndexView},
list::ListCursorMode, list::ListCursorMode,
product::{segment::ProductEditorSegment}, product::{segment::ProductEditorSegment},
make_editor::make_editor make_editor::make_editor
}, },
cgmath::Vector2, cgmath::{Vector2, Point2},
std::sync::{Arc, RwLock}, std::sync::{Arc, RwLock},
termion::event::{Event, Key}, termion::event::{Event, Key},
std::ops::{Deref, DerefMut}
}; };
pub struct ProductEditor { pub struct ProductEditor {
segments: VecBuffer<ProductEditorSegment>, segments: IndexBuffer<Point2<i16>, ProductEditorSegment>,
pub(super) n_indices: Vec<usize>, pub(super) n_indices: Vec<Point2<i16>>,
pub(super) ctx: Arc<RwLock<Context>>, pub(super) ctx: Arc<RwLock<Context>>,
pub(super) cursor: Option<isize>, pub(super) cursor: Option<isize>,
@ -29,7 +31,7 @@ pub struct ProductEditor {
impl ProductEditor { impl ProductEditor {
pub fn new(depth: usize, ctx: Arc<RwLock<Context>>) -> Self { pub fn new(depth: usize, ctx: Arc<RwLock<Context>>) -> Self {
ProductEditor { ProductEditor {
segments: VecBuffer::new(), segments: IndexBuffer::new(),
n_indices: Vec::new(), n_indices: Vec::new(),
ctx, ctx,
cursor: None, cursor: None,
@ -37,53 +39,52 @@ impl ProductEditor {
} }
} }
pub fn with_t(mut self, t: &str) -> Self { pub fn with_t(mut self, pos: Point2<i16>, t: &str) -> Self {
self.segments.push(ProductEditorSegment::T(t.to_string(), self.depth)); self.segments.insert(pos, ProductEditorSegment::T(t.to_string(), self.depth));
self self
} }
pub fn with_n(mut self, n: TypeLadder) -> Self { pub fn with_n(mut self, pos: Point2<i16>, n: TypeLadder) -> Self {
let elem_idx = self.segments.len(); self.segments.insert(pos, ProductEditorSegment::N{
self.segments.push(ProductEditorSegment::N{
t: n, t: n,
editor: None, editor: None,
cur_depth: 0 cur_depth: 0
}); });
self.n_indices.push(elem_idx); self.n_indices.push(pos);
self self
} }
pub fn get_editor_element(&self, mut idx: isize) -> Option<ProductEditorSegment> { pub fn get_editor_segment(&self, mut idx: isize) -> ProductEditorSegment {
idx = crate::modulo(idx, self.n_indices.len() as isize); idx = crate::modulo(idx, self.n_indices.len() as isize);
if let Some(i) = self.n_indices.get(idx as usize) { if let Some(pos) = self.n_indices.get(idx as usize) {
Some(self.segments.get(*i)) self.segments.get(pos).unwrap()
} else { } else {
None unreachable!()
} }
} }
pub fn get_editor_element_mut(&mut self, mut idx: isize) -> Option<MutableVecAccess<ProductEditorSegment>> { pub fn get_editor_segment_mut(&mut self, mut idx: isize) -> MutableIndexAccess<Point2<i16>, ProductEditorSegment> {
idx = crate::modulo(idx, self.n_indices.len() as isize); idx = crate::modulo(idx, self.n_indices.len() as isize);
if let Some(i) = self.n_indices.get(idx as usize) { if let Some(pos) = self.n_indices.get(idx as usize) {
Some(self.segments.get_mut(*i)) self.segments.get_mut(pos)
} else { } else {
None unreachable!()
} }
} }
pub fn get_cur_element(&self) -> Option<ProductEditorSegment> { pub fn get_cur_segment(&self) -> Option<ProductEditorSegment> {
self.get_editor_element(self.cursor?) Some(self.get_editor_segment(self.cursor?))
} }
pub fn get_cur_element_mut(&mut self) -> Option<MutableVecAccess<ProductEditorSegment>> { pub fn get_cur_segment_mut(&mut self) -> Option<MutableIndexAccess<Point2<i16>, ProductEditorSegment>> {
self.get_editor_element_mut(self.cursor?) Some(self.get_editor_segment_mut(self.cursor?))
} }
pub fn get_editor(&self, idx: isize) -> Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>> { pub fn get_editor(&self, idx: isize) -> Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>> {
if let Some(ProductEditorSegment::N{ t: _, editor, cur_depth: _ }) = self.get_editor_element(idx) { if let ProductEditorSegment::N{ t: _, editor, cur_depth: _ } = self.get_editor_segment(idx) {
editor editor
} else { } else {
None unreachable!()
} }
} }
@ -103,14 +104,13 @@ impl TerminalEditor for ProductEditor {
let ctx = self.ctx.clone(); let ctx = self.ctx.clone();
self.segments self.segments
.get_port() .get_port()
.to_sequence() .map_item(move |_pos, e: &ProductEditorSegment| { e.get_view(ctx.clone()) })
.map(move |e: &ProductEditorSegment| { e.get_view(ctx.clone()) })
.to_grid_horizontal()
.flatten() .flatten()
} }
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult { fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = self.get_cur_element_mut().as_deref_mut() { if let Some(mut segment) = self.get_cur_segment_mut().as_deref_mut() {
if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = segment.deref_mut() {
*cur_depth = self.get_cursor().tree_addr.len(); *cur_depth = self.get_cursor().tree_addr.len();
if let Some(e) = editor.clone() { if let Some(e) = editor.clone() {
let mut ce = e.write().unwrap(); let mut ce = e.write().unwrap();
@ -141,6 +141,9 @@ impl TerminalEditor for ProductEditor {
*cur_depth = self.get_cursor().tree_addr.len()+1; *cur_depth = self.get_cursor().tree_addr.len()+1;
x x
} }
} else {
unreachable!()
}
} else { } else {
TerminalEditorResult::Exit TerminalEditorResult::Exit
} }

View file

@ -52,8 +52,8 @@ impl TreeNav for ProductEditor {
} }
fn goto(&mut self, mut c: TreeCursor) -> TreeNavResult { fn goto(&mut self, mut c: TreeCursor) -> TreeNavResult {
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut segment) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t: _t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t: _t, editor, cur_depth }) = segment.deref_mut() {
if let Some(e) = editor { if let Some(e) = editor {
let mut e = e.write().unwrap(); let mut e = e.write().unwrap();
e.goto(TreeCursor::none()); e.goto(TreeCursor::none());
@ -65,8 +65,8 @@ impl TreeNav for ProductEditor {
if c.tree_addr.len() > 0 { if c.tree_addr.len() > 0 {
self.cursor = Some(crate::modulo(c.tree_addr.remove(0), self.n_indices.len() as isize)); self.cursor = Some(crate::modulo(c.tree_addr.remove(0), self.n_indices.len() as isize));
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t: _t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t: _t, editor, cur_depth }) = element.deref_mut() {
if let Some(e) = editor { if let Some(e) = editor {
e.write().unwrap().goto(c.clone()); e.write().unwrap().goto(c.clone());
} }
@ -89,8 +89,8 @@ impl TreeNav for ProductEditor {
if direction.y > 0 { if direction.y > 0 {
self.cursor = Some(0); self.cursor = Some(0);
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
*cur_depth = 1; *cur_depth = 1;
} }
} }
@ -106,8 +106,8 @@ impl TreeNav for ProductEditor {
1 => { 1 => {
if direction.y > 0 { if direction.y > 0 {
// dn // dn
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
if let Some(e) = editor { if let Some(e) = editor {
let mut e = e.write().unwrap(); let mut e = e.write().unwrap();
e.goby(direction); e.goby(direction);
@ -125,8 +125,8 @@ impl TreeNav for ProductEditor {
TreeNavResult::Continue TreeNavResult::Continue
} else if direction.y < 0 { } else if direction.y < 0 {
// up // up
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
*cur_depth = 0; *cur_depth = 0;
} }
} }
@ -137,14 +137,14 @@ impl TreeNav for ProductEditor {
if (cur.tree_addr[0]+direction.x >= 0) && if (cur.tree_addr[0]+direction.x >= 0) &&
(cur.tree_addr[0]+direction.x < self.n_indices.len() as isize) (cur.tree_addr[0]+direction.x < self.n_indices.len() as isize)
{ {
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
*cur_depth = 0; *cur_depth = 0;
} }
} }
self.cursor = Some(cur.tree_addr[0] + direction.x); self.cursor = Some(cur.tree_addr[0] + direction.x);
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
*cur_depth = 1; *cur_depth = 1;
} }
} }
@ -156,8 +156,8 @@ impl TreeNav for ProductEditor {
} }
} }
depth => { depth => {
if let Some(mut element) = self.get_cur_element_mut() { if let Some(mut element) = self.get_cur_segment_mut() {
if let ProductEditorSegment::N{ t, editor, cur_depth } = element.deref_mut() { if let Some(ProductEditorSegment::N{ t, editor, cur_depth }) = element.deref_mut() {
if let Some(e) = editor { if let Some(e) = editor {
let mut ce = e.write().unwrap(); let mut ce = e.write().unwrap();
//\\//\\//\\//\\ //\\//\\//\\//\\