product editor

This commit is contained in:
Michael Sippel 2022-05-08 23:30:49 +02:00
parent 61c2d55441
commit f118eada34
Signed by: senvas
GPG key ID: F96CF119C34B64A6
17 changed files with 821 additions and 68 deletions

View file

@ -1,8 +1,13 @@
use {
crate::core::{
type_term::{TypeDict, TypeTerm},
crate::{
core::{
type_term::{TypeDict, TypeTerm, TypeID},
AnyOuterViewPort, OuterViewPort, View,
},
tree_nav::{
TerminalTreeEditor
}
},
std::{
collections::HashMap,
sync::{Arc, RwLock},
@ -232,10 +237,20 @@ pub struct MorphismType {
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct Context {
/// assigns a name to every type
type_dict: TypeDict,
/// objects
objects: HashMap<String, Object>,
/// editors
editor_ctors: HashMap<TypeID, Box<dyn Fn(&Self, TypeTerm) -> Option<Arc<RwLock<dyn TerminalTreeEditor>>> + Send + Sync>>,
/// morphisms
default_constructors: HashMap<TypeTerm, Box<dyn Fn() -> Object + Send + Sync>>,
morphism_constructors: HashMap<MorphismType, Box<dyn Fn(Object) -> Object + Send + Sync>>,
objects: HashMap<String, Object>,
/// recursion
parent: Option<Arc<RwLock<Context>>>,
}
@ -243,6 +258,7 @@ impl Context {
pub fn with_parent(parent: Option<Arc<RwLock<Context>>>) -> Self {
Context {
type_dict: TypeDict::new(),
editor_ctors: HashMap::new(),
default_constructors: HashMap::new(),
morphism_constructors: HashMap::new(),
objects: HashMap::new(),
@ -261,6 +277,26 @@ impl Context {
pub fn type_term_from_str(&self, tn: &str) -> Option<TypeTerm> {
self.type_dict.type_term_from_str(&tn)
}
pub fn type_term_to_str(&self, t: &TypeTerm) -> String {
self.type_dict.type_term_to_str(&t)
}
pub fn add_editor_ctor(&mut self, tn: &str, mk_editor: Box<dyn Fn(&Self, TypeTerm) -> Option<Arc<RwLock<dyn TerminalTreeEditor>>> + Send + Sync>) {
if let Some(tid) = self.type_dict.get_typeid(&tn.into()) {
self.editor_ctors.insert(tid, mk_editor);
} else {
println!("invalid type name");
}
}
pub fn make_editor(&self, type_term: TypeTerm) -> Option<Arc<RwLock<dyn TerminalTreeEditor>>> {
if let TypeTerm::Type{ id, args } = type_term.clone() {
let mk_editor = self.editor_ctors.get(&id)?;
mk_editor(self, type_term)
} else {
None
}
}
pub fn add_morphism(
&mut self,

View file

@ -12,6 +12,6 @@ pub use {
port::{
AnyInnerViewPort, AnyOuterViewPort, AnyViewPort, InnerViewPort, OuterViewPort, ViewPort,
},
type_term::{TypeDict, TypeID, TypeTerm},
type_term::{TypeDict, TypeID, TypeTerm, TypeLadder},
view::View,
};

View file

@ -3,6 +3,7 @@ use {crate::bimap::Bimap, std::collections::HashMap};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub type TypeID = u64;
pub type TypeLadder = Vec<TypeTerm>;
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
@ -105,7 +106,7 @@ impl TypeTerm {
pub fn to_str(&self, names: &HashMap<u64, String>) -> String {
match self {
TypeTerm::Type { id, args } => format!(
"( {} {})",
"« {} {}»",
names[id],
if args.len() > 0 {
args.iter().fold(String::new(), |str, term| {
@ -141,6 +142,14 @@ impl TypeDict {
self.type_id_counter += 1;
}
pub fn get_typeid(&self, tn: &String) -> Option<TypeID> {
if let Some(id) = self.typenames..get(tn) {
Some(*id)
} else {
None
}
}
pub fn type_term_from_str(&self, typename: &str) -> Option<TypeTerm> {
TypeTerm::from_str(typename, &self.typenames.)
}

View file

@ -198,11 +198,11 @@ where
let old_limit = self.limit;
self.limit = Point2::new(
(0..=top_range.end().x as usize)
.map(|x| col_widths[x])
.map(|x| col_widths.get(x).unwrap_or(&0))
.sum::<i16>()
- 1,
(0..=top_range.end().y as usize)
.map(|y| row_heights[y])
.map(|y| row_heights.get(y).unwrap_or(&0))
.sum::<i16>()
- 1,
);

View file

@ -77,6 +77,8 @@ impl TerminalEditor for DigitEditor {
}
}
impl TerminalTreeEditor for DigitEditor {}
pub struct PosIntEditor {
radix: u32,
digits_editor:
@ -182,3 +184,6 @@ impl TerminalEditor for PosIntEditor {
}
}
}
impl TerminalTreeEditor for PosIntEditor {}

View file

@ -6,11 +6,13 @@ pub mod projection;
pub mod grid;
pub mod index;
pub mod integer;
pub mod product;
pub mod list;
pub mod sequence;
pub mod singleton;
pub mod terminal;
pub mod vec;
pub mod make_editor;
pub mod tree_nav;

View file

@ -22,6 +22,7 @@ use {
pub enum ListEditorStyle {
HorizontalSexpr,
VerticalSexpr,
Tuple(usize),
Path,
String,
Clist,
@ -189,6 +190,7 @@ where
return TreeNavResult::Continue;
}
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
}
}
@ -201,7 +203,7 @@ where
}
fn goto_home(&mut self) -> TreeNavResult {
let cur = self.cursor.get();
let mut cur = self.cursor.get();
if self.data.len() == 0 && cur.idx.is_none() {
self.cursor.set(ListCursor {
mode: ListCursorMode::Insert,
@ -228,7 +230,7 @@ where
}
}
ListCursorMode::Modify => {
let ce = self.get_item().unwrap();
if let Some(ce) = self.get_item() {
let mut cur_edit = ce.write().unwrap();
let cur_mode = cur_edit.get_cursor().leaf_mode;
let depth = cur_edit.get_cursor().tree_addr.len();
@ -238,8 +240,6 @@ where
drop(cur_edit);
if let Some(i) = cur.idx {
self.up();
if i > 0 {
self.set_mode(ListCursorMode::Select);
self.pxev();
@ -249,18 +249,20 @@ where
self.goto_end();
}
self.set_leaf_mode(cur_mode);
self.dn();
self.goto_home();
self.set_leaf_mode(cur_mode);
//self.goto_home();
return TreeNavResult::Continue;
}
}
}
TreeNavResult::Continue => { return TreeNavResult::Continue; }
};
}
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
}
TreeNavResult::Continue => TreeNavResult::Continue,
}
}
}
}
@ -279,19 +281,25 @@ where
TreeNavResult::Continue => {}
}
return TreeNavResult::Continue;
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
} else {
self.cursor.set(ListCursor {
mode: cur.mode,
idx: None,
});
TreeNavResult::Exit
}
}
fn dn(&mut self) -> TreeNavResult {
let cur = self.cursor.get();
let mut cur = self.cursor.get();
if cur.idx.is_none() {
self.goto_home()
} else {
match cur.mode {
ListCursorMode::Insert | ListCursorMode::Select => {
if let Some(i) = cur.idx {
@ -301,6 +309,7 @@ where
leaf_mode: cur.mode,
tree_addr: vec![],
});
self.data.get_mut(i).write().unwrap().dn();
*self.cur_dist.write().unwrap() += 1;
}
}
@ -309,6 +318,7 @@ where
ListCursorMode::Modify => self.get_item().unwrap().write().unwrap().dn(),
}
}
}
fn pxev(&mut self) -> TreeNavResult {
let mut cur = self.cursor.get();
@ -397,7 +407,7 @@ where
TreeNavResult::Exit => {
drop(cur_edit);
drop(ce);
self.up();
//self.up();
if i + 1 < self.data.len() {
self.set_mode(ListCursorMode::Select);
@ -405,14 +415,14 @@ where
for _x in 1..depth {
self.dn();
self.goto_home();
}
self.set_leaf_mode(cur_mode);
self.dn();
self.goto_home();
TreeNavResult::Continue
} else {
self.cursor.set(ListCursor::default());
TreeNavResult::Exit
}
}
@ -435,6 +445,7 @@ where
match self.style {
ListEditorStyle::HorizontalSexpr => self.horizontal_sexpr_view(),
ListEditorStyle::VerticalSexpr => self.vertical_sexpr_view(),
ListEditorStyle::Tuple(depth) => self.tuple_view(depth),
ListEditorStyle::Path => self.path_view(),
ListEditorStyle::String => self.string_view(),
ListEditorStyle::Clist => self.clist_view(),
@ -474,10 +485,10 @@ where
_ => {
let new_edit = (self.make_item_editor)();
self.data.insert(idx, new_edit.clone());
self.dn();
self.goto_home();
self.set_mode(ListCursorMode::Modify);
let mut ne = new_edit.write().unwrap();
match new_edit.write().unwrap().handle_terminal_event(event) {
match ne.handle_terminal_event(event) {
TerminalEditorResult::Exit => {
self.cursor.set(ListCursor {
mode: ListCursorMode::Insert,
@ -552,6 +563,12 @@ where
}
}
impl<ItemEditor, FnMakeItemEditor> TerminalTreeEditor for ListEditor<ItemEditor, FnMakeItemEditor>
where
ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
FnMakeItemEditor: Fn() -> Arc<RwLock<ItemEditor>> + Send + Sync,
{}
impl<ItemEditor, FnMakeItemEditor> ListEditor<ItemEditor, FnMakeItemEditor>
where
ItemEditor: TerminalTreeEditor + ?Sized + Send + Sync + 'static,
@ -633,6 +650,13 @@ where
.flatten()
}
pub fn tuple_view(&self, depth: usize) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view()
.decorate("(", ")", ", ", depth)
.to_grid_horizontal()
.flatten()
}
pub fn hex_view(&self) -> OuterViewPort<dyn TerminalView> {
self.get_seg_seq_view()
.decorate("0x", "", "", 0)
@ -738,3 +762,4 @@ where
self.goto(c);
}
}

View file

@ -224,6 +224,7 @@ impl VerticalSexprDecorator {
list_style: TerminalStyle::fg_color(match level {
0 => (200, 120, 10),
1 => (120, 200, 10),
2 => (200, 10, 120),
_ => (255, 255, 255),
}),
item_style: TerminalStyle::fg_color(match level {

113
nested/src/make_editor.rs Normal file
View file

@ -0,0 +1,113 @@
use {
crate::{
core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context},
terminal::{
Terminal, TerminalAtom, TerminalCompositor, TerminalEditor,
TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
make_label
},
sequence::{SequenceView},
tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult},
vec::{VecBuffer, MutableVecAccess},
index::buffer::IndexBuffer,
integer::PosIntEditor,
string_editor::{StringEditor, CharEditor},
list::{ListEditor, ListCursorMode, ListEditorStyle},
product::editor::ProductEditor
},
cgmath::{Point2, Vector2},
std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}},
termion::event::{Event, Key},
};
pub fn make_editor(ctx: Arc<RwLock<Context>>, t: &TypeLadder, depth: usize) -> Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>> {
let c = ctx.read().unwrap();
if t[0] == c.type_term_from_str("( PosInt 16 BigEndian )").unwrap() {
Arc::new(RwLock::new(PosIntEditor::new(16))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( PosInt 10 BigEndian )").unwrap() {
Arc::new(RwLock::new(PosIntEditor::new(10))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( String )").unwrap() {
Arc::new(RwLock::new(StringEditor::new())) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( List Char )").unwrap() {
Arc::new(RwLock::new(ListEditor::new(
|| { Arc::new(RwLock::new(CharEditor::new())) },
ListEditorStyle::Plain
))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( List )").unwrap() {
Arc::new(RwLock::new(ListEditor::new(
|| {
Arc::new(RwLock::new(PosIntEditor::new(16)))
},
ListEditorStyle::HorizontalSexpr
))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( Path )").unwrap() {
Arc::new(RwLock::new(ListEditor::new(
|| {
Arc::new(RwLock::new(ListEditor::new(
|| {
Arc::new(RwLock::new(CharEditor::new()))
},
ListEditorStyle::Plain
)))
},
ListEditorStyle::Path
))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( List RGB )").unwrap() {
Arc::new(RwLock::new(ListEditor::new({
let ctx = ctx.clone();
move || {
make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( RGB )").unwrap() ], depth+1)
}
},
ListEditorStyle::VerticalSexpr
))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} 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(" }")
)) 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(" }")
)) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} else if t[0] == c.type_term_from_str("( List Term )").unwrap() {
Arc::new(RwLock::new(ListEditor::new({
let ctx = ctx.clone();
move || {
make_editor(ctx.clone(), &vec![ ctx.read().unwrap().type_term_from_str("( Term )").unwrap() ], depth+1)
}
},
ListEditorStyle::Tuple(depth)
))) as Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>
} 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>>
}
}

View file

@ -0,0 +1,456 @@
use {
crate::{
core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context},
terminal::{
Terminal, TerminalAtom, TerminalCompositor, TerminalEditor,
TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
make_label
},
sequence::{SequenceView},
tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult},
vec::{VecBuffer, MutableVecAccess},
index::buffer::IndexBuffer,
integer::PosIntEditor,
string_editor::{StringEditor, CharEditor},
list::{ListEditor, ListCursorMode, ListEditorStyle},
product::{element::ProductEditorElement},
make_editor::make_editor
},
cgmath::{Point2, Vector2},
std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}},
termion::event::{Event, Key},
};
pub struct ProductEditor {
elements: VecBuffer<ProductEditorElement>,
n_indices: Vec<usize>,
el_port: OuterViewPort<dyn SequenceView<Item = ProductEditorElement>>,
el_view_port: OuterViewPort<dyn SequenceView<Item = OuterViewPort<dyn TerminalView>>>,
ctx: Arc<RwLock<Context>>,
cursor: Option<usize>,
depth: usize
}
impl ProductEditor {
pub fn new(depth: usize, ctx: Arc<RwLock<Context>>) -> Self {
let mut port = ViewPort::new();
let el_port = port.outer().to_sequence();
let el_view_port = el_port.map({
let ctx = ctx.clone();
move |e: &ProductEditorElement| { e.get_view(ctx.clone()) }
});
ProductEditor {
elements: VecBuffer::new(port.inner()),
el_port,
el_view_port,
n_indices: Vec::new(),
ctx,
cursor: None,
depth
}
}
pub fn with_t(mut self, t: &str) -> Self {
self.elements.push(ProductEditorElement::T(t.to_string()));
self
}
pub fn with_n(mut self, n: TypeLadder) -> Self {
let elem_idx = self.elements.len();
self.elements.push(ProductEditorElement::N{
t: n,
editor: None,
select: false
});
self.n_indices.push(elem_idx);
self
}
fn get_editor_element(&self, idx: usize) -> Option<ProductEditorElement> {
if let Some(i) = self.n_indices.get(idx) {
Some(self.elements.get(*i))
} else {
None
}
}
fn get_editor_element_mut(&mut self, idx: usize) -> Option<MutableVecAccess<ProductEditorElement>> {
if let Some(i) = self.n_indices.get(idx) {
Some(self.elements.get_mut(*i))
} else {
None
}
}
fn get_cur_element(&self) -> Option<ProductEditorElement> {
self.get_editor_element(self.cursor?)
}
fn get_cur_element_mut(&mut self) -> Option<MutableVecAccess<ProductEditorElement>> {
self.get_editor_element_mut(self.cursor?)
}
fn get_editor(&self, idx: usize) -> Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>> {
if let Some(ProductEditorElement::N{ t: _, editor, select: _ }) = self.get_editor_element(idx) {
editor
} else {
None
}
}
fn get_cur_editor(&self) -> Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>> {
self.get_editor(self.cursor?)
}
fn set_leaf_mode(&mut self, mode: ListCursorMode) {
let mut c = self.get_cursor();
c.leaf_mode = mode;
self.goto(c);
}
}
impl TreeNav for ProductEditor {
fn get_cursor(&self) -> TreeCursor {
if let Some(i) = self.cursor {
if let Some(e) = self.get_editor(i) {
let mut c = e.read().unwrap().get_cursor();
if c.tree_addr.len() == 0 {
c.leaf_mode = ListCursorMode::Select;
}
c.tree_addr.insert(0, i);
c
} else {
TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![ i ]
}
}
} else {
TreeCursor::default()
}
}
fn goto(&mut self, mut c: TreeCursor) -> TreeNavResult {
if let Some(mut element) = self.get_cur_element_mut() {
if let ProductEditorElement::N{ t, editor, select } = element.deref_mut() {
if let Some(e) = editor {
e.write().unwrap().goto(TreeCursor::default());
}
*select = false;
}
}
if c.tree_addr.len() > 0 {
self.cursor = Some(c.tree_addr.remove(0));
if let Some(mut element) = self.get_cur_element_mut() {
if let ProductEditorElement::N{ t, editor, select } = element.deref_mut() {
if let Some(e) = editor {
e.write().unwrap().goto(c);
}
*select = true;
}
}
TreeNavResult::Continue
} else {
self.cursor = None;
TreeNavResult::Exit
}
}
fn goto_home(&mut self) -> TreeNavResult {
if let Some(c) = self.cursor {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
if let Some(e) = editor {
let mut ce = e.write().unwrap();
let cur_mode = ce.get_cursor().leaf_mode;
let depth = ce.get_cursor().tree_addr.len();
if depth > 0 {
return match ce.goto_home() {
TreeNavResult::Exit => {
drop(ce);
*select = false;
match self.pxev() {
TreeNavResult::Exit => TreeNavResult::Exit,
TreeNavResult::Continue => {
for _x in 1..depth {
self.dn();
self.goto_end();
}
self.dn();
self.set_leaf_mode(cur_mode);
TreeNavResult::Continue
}
}
},
TreeNavResult::Continue => TreeNavResult::Continue
};
}
}
*select = false;
if c != 0 {
self.cursor = Some(0);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
return TreeNavResult::Continue;
}
}
}
self.cursor = None;
TreeNavResult::Exit
}
fn goto_end(&mut self) -> TreeNavResult {
if let Some(c) = self.cursor {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
if let Some(e) = editor {
let mut ce = e.write().unwrap();
let cur_mode = ce.get_cursor().leaf_mode;
let depth = ce.get_cursor().tree_addr.len();
if depth > 0 {
return match ce.goto_end() {
TreeNavResult::Exit => {
drop(ce);
*select = false;
match self.nexd() {
TreeNavResult::Exit => TreeNavResult::Exit,
TreeNavResult::Continue => {
for _x in 1..depth {
self.dn();
}
self.dn();
self.set_leaf_mode(cur_mode);
self.goto_end();
TreeNavResult::Continue
}
}
},
TreeNavResult::Continue => TreeNavResult::Continue
};
}
}
*select = false;
if c < self.n_indices.len()-1 {
self.cursor = Some(self.n_indices.len()-1);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
return TreeNavResult::Continue;
}
}
}
self.cursor = None;
TreeNavResult::Exit
}
fn pxev(&mut self) -> TreeNavResult {
if let Some(c) = self.cursor {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() {
if let Some(e) = editor {
let mut ce = e.write().unwrap();
let depth = ce.get_cursor().tree_addr.len();
let cur_mode = ce.get_cursor().leaf_mode;
if depth > 0 {
return match ce.pxev() {
TreeNavResult::Exit => {
drop(ce);
*select = false;
if c > 0 {
self.cursor = Some(c-1);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
for _x in 1..depth {
self.dn();
self.goto_end();
}
self.dn();
self.set_leaf_mode(cur_mode);
self.goto_end();
TreeNavResult::Continue
} else {
TreeNavResult::Exit
}
}
TreeNavResult::Continue => TreeNavResult::Continue
};
}
}
*select = false;
if c > 0 {
self.cursor = Some(c-1);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
return TreeNavResult::Continue;
}
}
}
self.cursor = None;
TreeNavResult::Exit
}
fn nexd(&mut self) -> TreeNavResult {
if let Some(c) = self.cursor.clone() {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() {
if let Some(e) = editor {
let mut ce = e.write().unwrap();
let depth = ce.get_cursor().tree_addr.len();
let cur_mode = ce.get_cursor().leaf_mode;
if depth > 0 {
return match ce.nexd() {
TreeNavResult::Exit => {
drop(ce);
*select = false;
if c+1 < self.n_indices.len() {
self.cursor = Some(c+1);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
for _x in 1..depth {
self.dn();
}
self.dn();
self.set_leaf_mode(cur_mode);
TreeNavResult::Continue
} else {
self.cursor = None;
TreeNavResult::Exit
}
}
TreeNavResult::Continue => TreeNavResult::Continue
};
}
}
*select = false;
if c+1 < self.n_indices.len() {
self.cursor = Some(c+1);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
return TreeNavResult::Continue;
}
}
}
self.cursor = None;
TreeNavResult::Exit
}
fn up(&mut self) -> TreeNavResult {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
if let Some(e) = editor {
let mut ce = e.write().unwrap();
if ce.get_cursor().tree_addr.len() > 0 {
ce.up();
return TreeNavResult::Continue;
}
}
*select = false;
}
self.cursor = None;
TreeNavResult::Exit
}
fn dn(&mut self) -> TreeNavResult {
if let Some(c) = self.cursor {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_editor_element_mut(c).as_deref_mut() {
if let Some(e) = editor {
e.write().unwrap().dn();
} else {
let e = make_editor(self.ctx.clone(), t, self.depth+1);
e.write().unwrap().goto_home();
*editor = Some(e);
}
}
} else {
self.cursor = Some(0);
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
}
}
TreeNavResult::Continue
}
}
impl TerminalEditor for ProductEditor {
fn get_term_view(&self) -> OuterViewPort<dyn TerminalView> {
self.el_view_port.to_grid_horizontal().flatten()
}
fn handle_terminal_event(&mut self, event: &TerminalEvent) -> TerminalEditorResult {
if let Some(ProductEditorElement::N{ t, editor, select }) = self.get_cur_element_mut().as_deref_mut() {
*select = true;
if let Some(e) = editor.clone() {
match e.clone().write().unwrap().handle_terminal_event(event) {
TerminalEditorResult::Exit =>
match event {
TerminalEvent::Input(Event::Key(Key::Backspace)) => {
*editor = None;
TerminalEditorResult::Continue
}
_ => {
drop(e);
match self.nexd() {
TreeNavResult::Continue => TerminalEditorResult::Continue,
TreeNavResult::Exit => TerminalEditorResult::Exit
}
}
},
TerminalEditorResult::Continue =>
TerminalEditorResult::Continue
}
} else {
let e = make_editor(self.ctx.clone(), t, self.depth+1);
*editor = Some(e.clone());
e.write().unwrap().dn();
let x = e.write().unwrap().handle_terminal_event(event);
x
}
} else {
TerminalEditorResult::Exit
}
}
}
impl TerminalTreeEditor for ProductEditor {}

View file

@ -0,0 +1,74 @@
use {
crate::{
core::{ViewPort, OuterViewPort, Observer, port::UpdateTask, TypeTerm, TypeLadder, Context},
terminal::{
Terminal, TerminalAtom, TerminalCompositor, TerminalEditor,
TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
make_label
},
sequence::{SequenceView},
tree_nav::{TreeNav, TerminalTreeEditor, TreeCursor, TreeNavResult},
vec::{VecBuffer, MutableVecAccess},
index::buffer::IndexBuffer,
integer::PosIntEditor,
string_editor::{StringEditor, CharEditor},
list::{ListEditor, ListCursorMode, ListEditorStyle}
},
cgmath::{Point2, Vector2},
std::{sync::{Arc, RwLock}, ops::{Deref, DerefMut}},
termion::event::{Event, Key},
};
#[derive(Clone)]
pub enum ProductEditorElement {
T( String ),
N {
t: TypeLadder,
editor: Option<Arc<RwLock<dyn TerminalTreeEditor + Send + Sync>>>,
select: bool
}
}
impl ProductEditorElement {
pub fn get_view(&self, ctx: Arc<RwLock<Context>>) -> OuterViewPort<dyn TerminalView> {
match self {
ProductEditorElement::T(t) =>
make_label(t.as_str())
.map_item(
|i, x|
x.add_style_back(TerminalStyle::fg_color((0,120,200)))
),
ProductEditorElement::N {t: _, editor: Some(e), select} =>
e.read().unwrap()
.get_term_view()
.map_item({ let select = *select;
move |i, x| x
.add_style_back(TerminalStyle::fg_color((250,210,0)))
.add_style_back(
if select {
TerminalStyle::bg_color((40,40,40))
} else {
TerminalStyle::default()
}
)
}),
ProductEditorElement::N{t, editor: None, select} =>
make_label(&ctx.read().unwrap().type_term_to_str(&t[0]))
.map_item({ let select = *select;
move |i, x| x
.add_style_back(TerminalStyle::fg_color((130,90,40)))
.add_style_back(
if select {
TerminalStyle::bg_color((40,40,40))
} else {
TerminalStyle::default()
}
)
})
}
}
}

View file

@ -0,0 +1,4 @@
pub mod editor;
pub mod element;

View file

@ -82,10 +82,10 @@ where
{
fn reset(&mut self, view: Option<Arc<SrcView>>) {
self.src_view = view;
self.cast.notify(&IndexArea::Full);
self.cast.notify(&IndexArea::Set(vec![ () ]));
}
fn notify(&mut self, _: &()) {
self.cast.notify(&IndexArea::Full);
self.cast.notify(&IndexArea::Set(vec![ () ]));
}
}

View file

@ -2,12 +2,12 @@ use {
crate::{
core::{OuterViewPort, ViewPort},
list::{sexpr::ListDecoration, ListEditor},
sequence::SequenceView,
sequence::{SequenceView, SequenceViewExt},
singleton::{SingletonBuffer, SingletonView},
terminal::{
TerminalEditor, TerminalEditorResult, TerminalEvent, TerminalStyle, TerminalView,
},
tree_nav::{TreeCursor, TreeNav, TreeNavResult},
tree_nav::{TreeCursor, TreeNav, TreeNavResult, TerminalTreeEditor},
},
std::sync::Arc,
std::sync::RwLock,
@ -62,6 +62,8 @@ impl TerminalEditor for CharEditor {
}
}
impl TerminalTreeEditor for CharEditor {}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct StringEditor {
@ -82,7 +84,18 @@ impl StringEditor {
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = char>> {
self.chars_editor
.get_data_port()
.map(|char_editor| char_editor.read().unwrap().data.get().unwrap())
.map(|char_editor| char_editor.read().unwrap().data.get().unwrap_or('?'))
}
pub fn get_plain_editor_view(&self) -> OuterViewPort<dyn TerminalView> {
self.chars_editor
.get_seg_seq_view()
.to_grid_horizontal()
.flatten()
}
pub fn get_string(&self) -> String {
self.get_data_port().get_view().unwrap().iter().collect()
}
}
@ -109,7 +122,7 @@ impl TreeNav for StringEditor {
self.chars_editor.up()
}
fn dn(&mut self) -> TreeNavResult {
TreeNavResult::Exit
self.chars_editor.dn()
}
}
@ -133,3 +146,6 @@ impl TerminalEditor for StringEditor {
}
}
}
impl TerminalTreeEditor for StringEditor {}

View file

@ -5,6 +5,7 @@ pub enum TreeNavResult {
Continue,
Exit,
}
/*
impl From<TreeNavResult> for TerminalEditorResult {
fn from(v: TreeNavResult) -> TerminalEditorResult {
@ -15,12 +16,22 @@ impl From<TreeNavResult> for TerminalEditorResult {
}
}
*/
#[derive(Clone, Eq, PartialEq)]
pub struct TreeCursor {
pub leaf_mode: ListCursorMode,
pub tree_addr: Vec<usize>,
}
impl TreeCursor {
pub fn home() -> Self {
TreeCursor {
leaf_mode: ListCursorMode::Select,
tree_addr: vec![0]
}
}
}
impl Default for TreeCursor {
fn default() -> Self {
TreeCursor {
@ -66,4 +77,5 @@ pub trait TreeNav {
use crate::terminal::{TerminalEditor};
pub trait TerminalTreeEditor = TerminalEditor + TreeNav;
pub trait TerminalTreeEditor : TerminalEditor + TreeNav + Send {}

View file

@ -3,7 +3,7 @@ pub mod vec2bin;
pub mod vec2json;
pub mod vec2seq;
pub use buffer::VecBuffer;
pub use buffer::{VecBuffer, MutableVecAccess};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>