lib-nested/lib-nested-core/src/editors/integer/editor.rs

253 lines
7.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use {
r3vi::{
view::{
OuterViewPort,
singleton::*,
},
buffer::{
singleton::*,
vec::*,
index_hashmap::*
}
},
laddertypes::{TypeTerm},
crate::{
editors::{list::{ListCmd}, ObjCommander},
repr_tree::{Context, ReprTree},
edit_tree::{EditTree, TreeNav, TreeNavResult, TreeCursor, diagnostics::{Message}},
},
std::sync::Arc,
std::sync::RwLock,
std::iter::FromIterator,
cgmath::{Point2}
};
pub fn init_ctx( ctx: Arc<RwLock<Context>> ) {
// todo: proper scoping of Radix variable
ctx.write().unwrap().add_varname("Radix");
let morphtype =
crate::repr_tree::MorphismType {
src_type: Context::parse(&ctx, "<Digit Radix>"),
dst_type: Context::parse(&ctx, "<Digit Radix>~EditTree")
};
ctx.write().unwrap()
.morphisms
.add_morphism(
morphtype,
{
let ctx = ctx.clone();
move |rt, σ| {
let radix =
match σ.get( &laddertypes::TypeID::Var(ctx.read().unwrap().get_var_typeid("Radix").unwrap()) ) {
Some(TypeTerm::Num(n)) => *n as u32,
_ => 0
};
/* Create EditTree object
*/
let mut edittree_digit = DigitEditor::new(
ctx.clone(),
radix
).into_node(
r3vi::buffer::singleton::SingletonBuffer::<usize>::new(0).get_port()
);
/* Insert EditTree into ReprTree
*/
let mut rt = rt.write().unwrap();
rt.insert_leaf(
vec![ Context::parse(&ctx, "EditTree") ].into_iter(),
SingletonBuffer::new( Arc::new(RwLock::new(edittree_digit)) ).get_port().into()
);
}
}
);
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub struct DigitEditor {
ctx: Arc<RwLock<Context>>,
radix: u32,
data: SingletonBuffer<Option<char>>,
msg: VecBuffer<Message>,
}
impl ObjCommander for DigitEditor {
fn send_cmd_obj(&mut self, cmd_obj: Arc<RwLock<ReprTree>>) -> TreeNavResult {
let cmd_obj = cmd_obj.read().unwrap();
let cmd_type = cmd_obj.get_type().clone();
if cmd_type == Context::parse(&self.ctx, "Char") {
if let Some(cmd_view) = cmd_obj.get_view::<dyn SingletonView<Item = char>>() {
let c = cmd_view.get();
self.msg.clear();
if self.ctx.read().unwrap().meta_chars.contains(&c) {
return TreeNavResult::Exit;
} else if c.to_digit(self.radix).is_none() {
/* in case the character c is not in the range of digit-chars,
add a message to the diagnostics view
*/
/*
let message = IndexBuffer::from_iter(vec![
(Point2::new(1, 0), make_label("invalid digit '")),
(Point2::new(2, 0), make_label(&format!("{}", c))
.map_item(|_p,a| a.add_style_back(TerminalStyle::fg_color((140,140,250))))),
(Point2::new(3, 0), make_label("'"))
]);
self.msg.push(crate::diagnostics::make_error(message.get_port().flatten()));
*/
self.data.set(Some(c));
} else {
self.data.set(Some(c));
}
}
}
TreeNavResult::Continue
}
}
impl DigitEditor {
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
DigitEditor {
ctx,
radix,
data: SingletonBuffer::new(None),
msg: VecBuffer::new(),
}
}
pub fn into_node(self, depth: OuterViewPort<dyn SingletonView<Item = usize>>) -> EditTree {
let data = self.get_data();
let editor = Arc::new(RwLock::new(self));
let ed = editor.write().unwrap();
let r = ed.radix;
EditTree::new(ed.ctx.clone(), depth)
.set_editor(editor.clone())
.set_cmd(editor.clone())
.set_diag(
ed.msg.get_port().to_sequence()
)
}
pub fn attach_to(&mut self, source: OuterViewPort<dyn SingletonView<Item = u32>>) {
/*
source.add_observer(
Arc::new(NotifyFnObserver::new(|_msg| {
self.data.set( source.get() )
}))
);
*/
}
pub fn get_data_port(&self) -> OuterViewPort<dyn SingletonView<Item = Result<u32, char>>> {
let radix = self.radix;
self.data.get_port().map(move |c|
if let Some(d) = c.unwrap_or('?').to_digit(radix) {
Ok(d)
} else {
Err(c.unwrap_or('?'))
}
)
}
pub fn get_type(&self) -> TypeTerm {
TypeTerm::TypeID(self.ctx.read().unwrap().get_typeid("Digit").unwrap())
}
pub fn get_data(&self) -> Arc<RwLock<ReprTree>> {
ReprTree::ascend(
&ReprTree::new_leaf(
self.ctx.read().unwrap().type_term_from_str("<Seq u32>").unwrap(),
self.get_data_port().into()
),
self.get_type()
)
}
}
pub struct PosIntEditor {
radix: u32,
digits: EditTree,
// todo: endianness
}
impl PosIntEditor {
pub fn new(ctx: Arc<RwLock<Context>>, radix: u32) -> Self {
PosIntEditor {
radix,
digits: EditTree::new(
ctx,
r3vi::buffer::singleton::SingletonBuffer::new(0).get_port()
)
}
}
pub fn from_u64(ctx: Arc<RwLock<Context>>, radix: u32, value: u64) -> Self {
let mut edit = PosIntEditor::new(ctx, radix);
edit.set_value_u64( value );
edit
}
pub fn set_value_u64(&mut self, mut value: u64) {
self.digits.send_cmd_obj(ListCmd::Clear.into_repr_tree(&self.digits.ctx));
while value > 0 {
let digit_val = (value % self.radix as u64) as u32;
value /= self.radix as u64;
// if BigEndian
self.digits.goto(TreeCursor::home());
self.digits.send_cmd_obj(ReprTree::from_char(&self.digits.ctx, char::from_digit(digit_val, self.radix).expect("invalid digit")));
}
self.digits.goto(TreeCursor::none());
}
pub fn into_node(self) -> EditTree {
self.digits
}
/*
pub fn get_data_port(&self) -> OuterViewPort<dyn SequenceView<Item = u32>> {
let radix = self.radix;
self.digits
.get_data_port()
.filter_map(move |digit_editor| {
digit_editor.read().unwrap().data.get()?.to_digit(radix)
})
}
pub fn get_value(&self) -> u32 {
let mut value = 0;
let mut weight = 1;
for digit_value in self
.get_data_port()
.get_view()
.unwrap()
.iter()
.collect::<Vec<_>>()
.into_iter()
.rev()
{
value += digit_value * weight;
weight *= self.radix;
}
value
}
*/
}