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},
},
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>>>)
@ -36,6 +36,7 @@ where
}
}
#[derive(Clone)]
pub struct IndexBuffer<Key, Item>
where
Key: Clone + Hash + Eq + Send + Sync + 'static,
@ -68,6 +69,27 @@ where
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) {
self.data.write().unwrap().insert(key.clone(), item);
self.port.notify(&IndexArea::Set(vec![key]));
@ -87,3 +109,48 @@ where
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,
char_editor::CharEditor
},
cgmath::Vector2,
cgmath::{Vector2, Point2},
std::sync::{Arc, RwLock},
};
@ -90,26 +90,46 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else if t[0] == c.type_term_from_str("( RGB )").unwrap() {
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_t("{ r: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(", g: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(", b: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(" }")
.with_t(Point2::new(0, 0), "{")
.with_t(Point2::new(1, 1), "r: ")
.with_n(Point2::new(2, 1), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 2), "g: ")
.with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 16 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 3), "b: ")
.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>>
} else if t[0] == c.type_term_from_str("( Vec3i )").unwrap() {
Arc::new(RwLock::new(ProductEditor::new(depth, ctx.clone())
.with_t("{ x: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(", y: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(", z: ")
.with_n( vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(" }")
.with_t(Point2::new(0, 0), "{")
.with_t(Point2::new(1, 1), "x: ")
.with_n(Point2::new(2, 1), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 2), "y: ")
.with_n(Point2::new(2, 2), vec![ ctx.read().unwrap().type_term_from_str("( PosInt 10 BigEndian )").unwrap() ] )
.with_t(Point2::new(1, 3), "z: ")
.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>>
} else if t[0] == c.type_term_from_str("( List Term )").unwrap() {
Arc::new(RwLock::new(
PTYListEditor::<dyn TerminalTreeEditor + Send + Sync>::new(
@ -126,10 +146,15 @@ pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> A
} else { // else: term
Arc::new(RwLock::new(
ProductEditor::new(depth, ctx.clone())
.with_n( vec![ c.type_term_from_str("( List Char )").unwrap() ] )
.with_n( vec![ c.type_term_from_str("( List Term )").unwrap() ] )
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
PTYListEditor::new(
Box::new(|| {
Arc::new(RwLock::new(CharEditor::new()))
}),
SeqDecorStyle::DoubleQuote,
depth
)
))
}
}

View file

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

View file

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