use orbtk::prelude::*; use rhai::RegisterFn; use rhai::{Array, Engine}; use std::sync::mpsc::{Receiver, Sender}; use std::time::Duration; pub mod parser; pub mod widget_builders; use crate::parser::QML; use crate::parser::{parse_qml, Value}; use crate::widget_builders::{QmlContext, QmlWidgetBuilder}; use evmap::{ReadHandle, WriteHandle}; use rand::Rng; use std::borrow::BorrowMut; use std::collections::VecDeque; use std::ops::Index; use std::sync::mpsc; #[macro_use] extern crate pest_derive; #[derive(AsAny)] pub struct MainViewState { pub imports: Vec, pub qml: Vec<(String, QML)>, pub rx: Option>, } impl Widget for MainViewState { fn new() -> Self { unimplemented!() } fn build(self, ctx: &mut BuildContext) -> Entity { let top_level = self.qml.clone(); let widget = ctx.create_entity(); let (tx, rx): (Sender<(String, String, String)>, Receiver<(String, String, String)>) = mpsc::channel(); let (txf, rxf): (Sender<(String, String, String)>, Receiver<(String, String, String)>) = mpsc::channel(); let (r, w) = evmap::new(); let mut qmlctx = QmlContext { indexes: vec![], code: Default::default(), }; let this = QmlWidgetBuilder::new().build(widget, 0, 0, top_level[0].0.clone(), top_level[0].1.clone(), ctx, qmlctx.borrow_mut()); //render_ctx(widget, ctx, &top_level, 0, 0, ids.borrow_mut()).unwrap(); ctx.register_property("dirty", widget, false); ctx.register_state( this, Box::new(MVState { tx: Some(tx.clone()), rx: Some(rxf), engine: Engine::new(), codes: VecDeque::new(), ids: qmlctx.clone(), value_map: (None, Some(w)), }), ); let mut codes = VecDeque::new(); codes.push_back(String::new()); codes.push_back(String::new()); codes.push_back(String::new()); ctx.register_state( widget, Box::new(MVState { rx: Some(rx), tx: Some(txf), engine: Engine::new(), codes: codes, ids: qmlctx.clone(), value_map: (Some(r), None), }), ); this } fn insert_handler(self, _handler: impl Into>) -> Self { self } fn child(self, _child: Entity) -> Self { self } } #[derive(AsAny)] pub struct MVState { pub engine: Engine, pub tx: Option>, pub rx: Option>, pub codes: VecDeque, pub ids: QmlContext, pub value_map: (Option>, Option>), } impl MVState { fn action(&mut self, code: String) { match self.tx.clone() { Some(tx) => { let _ftx = tx.clone(); self.engine.register_fn("update_property", move |x: &str, y: &str, z: &str| { tx.send((String::from(x), String::from(y), String::from(z))); }); let r = self.value_map.0.as_ref().unwrap().clone(); self.engine.register_fn("get_property", move |x: &str, y: &str| -> String { let key = format!("{}.{}", x, y); if r.contains_key(key.as_str()) { return String::from(r.get_one(key.as_str()).unwrap().as_str()); } String::new() }); let result = self.engine.eval::<()>(code.as_str()); println!("{:?}", result); } _ => {} } } } impl State for MVState { fn init(&mut self, registry: &mut Registry, ctx: &mut Context) { self.update(registry, ctx); } fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) { match self.value_map.1.borrow_mut() { Some(w) => { self.engine.register_fn("rand_opacity", move || -> (f32) { let mut rng = rand::thread_rng(); rng.gen_range(0.0, 1.0) as f32 }); for id in self.ids.indexes.iter() { if ctx.child(id.as_str()).has::("text") { let res = ctx.child(id.as_str()).get::("text").clone(); let key = format!("{}.text", id); if w.contains_value(&key, &res.as_string()) == false { println!("Updating to {}", res.as_string()); } w.update(id.clone() + ".text", res.as_string()); } if ctx.child(id.as_str()).has::("selected_index") { let index = ctx.child(id.as_str()).get::("selected_index").clone(); match self.ids.code.get(&(id.clone(), String::from("items").clone())) { Some(code) => { let engine = Engine::new(); match engine.eval::(code.as_str()) { Ok(list) => { w.update(id.clone() + ".selected", list.index(index as usize).to_string()); } _ => {} } } _ => {} } } } w.refresh(); } _ => {} } let _tx = self.tx.clone().unwrap().clone(); match &self.rx { Some(rx) => match rx.recv_timeout(Duration::from_millis(1)) { Ok((x, y, z)) => { ctx.child(x.as_str()).set::(y.as_str(), String16::from(z)); } _ => {} }, _ => {} } } } impl Template for MainViewState {} pub fn state<'a>(id: Entity, states: &'a mut StatesContext) -> &'a mut MVState { states.get_mut(id) }