159 lines
5.8 KiB
Rust
159 lines
5.8 KiB
Rust
|
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
|
||
|
}
|