rqml/src/lib.rs

184 lines
6.1 KiB
Rust

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<String>,
pub qml: Vec<(String, QML)>,
pub rx: Option<Receiver<String>>,
}
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<Rc<dyn EventHandler>>) -> Self {
self
}
fn child(self, _child: Entity) -> Self {
self
}
}
#[derive(AsAny)]
pub struct MVState {
pub engine: Engine,
pub tx: Option<Sender<(String, String, String)>>,
pub rx: Option<Receiver<(String, String, String)>>,
pub codes: VecDeque<String>,
pub ids: QmlContext,
pub value_map: (Option<ReadHandle<String, String>>, Option<WriteHandle<String, String>>),
}
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::<String16>("text") {
let res = ctx.child(id.as_str()).get::<String16>("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::<i32>("selected_index") {
let index = ctx.child(id.as_str()).get::<i32>("selected_index").clone();
match self.ids.code.get(&(id.clone(), String::from("items").clone())) {
Some(code) => {
let engine = Engine::new();
match engine.eval::<Array>(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::<String16>(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)
}