rqml/src/main.rs

159 lines
5.8 KiB
Rust
Raw Normal View History

2020-07-04 18:35:37 +00:00
use orbtk::prelude::*;
extern crate pest;
#[macro_use]
extern crate pest_derive;
use pest::Parser;
use pest::iterators::{Pair, Pairs};
use crate::Value::{QmlString, QmlNumber, QmlIdent};
use std::borrow::Borrow;
#[derive(Parser)]
#[grammar = "../pest/qml.pest"]
struct QmlParser;
pub mod components;
#[derive(Debug, Clone)]
enum Value {
QmlString(String),
QmlNumber(f64),
QmlIdent(String),
}
#[derive(Debug, Clone)]
struct QML {
properties: HashMap<String, Value>,
children: HashMap<String, QML>
}
fn parse_qml(qml: Pairs<Rule>) -> QML {
let mut qmldoc = QML { properties: Default::default(), children: Default::default()};
for pair in qml {
// println!("Rule {:?} Str {}", pair.as_rule(), pair.as_str());
match pair.as_rule() {
Rule::import => {
let mut tokens = pair.into_inner();
println!("Found new Import {} ", tokens.next().unwrap().as_str());
},
Rule::body => {
let mut tokens = pair.into_inner();
let ident = tokens.next().unwrap().as_str();
println!("Found new Body: {} ", ident);
qmldoc.children.insert(String::from(ident), parse_qml(tokens.into_iter()));
},
Rule::property => {
let mut tokens = pair.into_inner();
let ident = tokens.next().unwrap().as_str();
let value = tokens.next().unwrap();
// let value = tokens.next().unwrap().as_str();
match value.as_rule() {
Rule::number => {
let num: f64 = value.as_str().parse().unwrap();
println!("Found new Property: {} {:?}", ident, num);
qmldoc.properties.insert(String::from(ident), QmlNumber(num));
}
Rule::string => {
println!("Found new Property: {} {}", ident, value.as_str());
qmldoc.properties.insert(String::from(ident), QmlString(String::from(value.into_inner().next().unwrap().as_str())));
}
Rule::ident => {
println!("Found new Property: {} {}", ident, value.as_str());
qmldoc.properties.insert(String::from(ident), QmlIdent(String::from(value.as_str())));
}
_ => {}
}
},
_ => return parse_qml(pair.into_inner())
}
}
qmldoc
}
fn main() {
Application::new()
.window(|ctx| {
let qml = include_str!("../res/example.qml");
let qml_tokens = QmlParser::parse(Rule::qml, qml).unwrap_or_else(|e| panic!("{}", e));
let qml_doc = parse_qml(qml_tokens);
let top_level = qml_doc.children.clone();
let width = match top_level.get("Rectangle").unwrap().properties.get("width").unwrap() {
QmlNumber(num) => num.clone(),
_ => {0.0}
};
let height = match top_level.get("Rectangle").unwrap().properties.get("height").unwrap() {
QmlNumber(num) => num.clone(),
_ => {0.0}
};
println!("{:?}",qml_doc);
Window::create()
.title("QML")
.position((100.0, 100.0))
.resizeable(true)
.size(width, height)
.child(render_ctx(ctx, &top_level).unwrap())
.build(ctx)
})
.run();
}
fn render_ctx(ctx: &mut BuildContext, qml: &HashMap<String, QML>) -> Option<Entity> {
for (ident, child) in qml.iter() {
match ident.as_str() {
"Rectangle" => {
let width = match child.properties.get("width").unwrap() {
QmlNumber(num) => num.clone(),
_ => {0.0}
};
let height = match child.properties.get("height").unwrap() {
QmlNumber(num) => num.clone(),
_ => {0.0}
};
let color = match child.properties.get("color").unwrap() {
QmlString(col) => match col.as_str() {
"red" => Color::rgb(0xff,00,00),
_ => Color::rgb(0xff,0xff,0xff)
}
_ => Color::rgb(0xff,0xff,0xff)
};
if child.children.len() == 0 {
return Some(Container::create().width(width).height(height).background(color).build(ctx))
} else {
match render_ctx(ctx, child.children.borrow()) {
Some(entity) => {
return Some(Container::create().width(width).height(height).background(color).child(entity).build(ctx))
}
_ => return Some(Container::create().width(width).height(height).background(color).build(ctx))
}
}
},
"Text" => {
let text = match child.properties.get("text").unwrap() {
QmlString(text) => text.clone(),
_ => {String::new()}
};
let mut tt = TextBlock::create();
tt = tt.text(text);
match child.properties.get("anchors.centerIn").unwrap() {
QmlIdent(str) => {
if str.eq("parent") {
tt = tt.vertical_alignment(Alignment::Center);
tt = tt.horizontal_alignment(Alignment::Center);
}
},
_ => {}
}
return Some(tt.build(ctx))
}
_ => {println!("unknown ident {}", ident)}
}
}
None
}