initial commit - red rectangle
This commit is contained in:
commit
26570d6073
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
.idea
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "rqml"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pest = "2.1.3"
|
||||||
|
pest_derive = "2.1.0"
|
||||||
|
orbtk = "0.3.1-alpha1"
|
||||||
|
specs = { version = "0.16.1", features = ["specs-derive"] }
|
|
@ -0,0 +1,5 @@
|
||||||
|
rqml is an experimental ui toolkit for rust.
|
||||||
|
|
||||||
|
Parsing the QML files into a hierarchy
|
||||||
|
|
||||||
|
Parsing the hierarchy into something that can be rendered.
|
|
@ -0,0 +1,29 @@
|
||||||
|
COMMENT = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
|
||||||
|
string = ${ "\"" ~ inner ~ "\"" }
|
||||||
|
inner = @{ char* }
|
||||||
|
char = {
|
||||||
|
!("\"" | "\\") ~ ANY
|
||||||
|
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
|
||||||
|
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
|
||||||
|
}
|
||||||
|
|
||||||
|
number = @{
|
||||||
|
"-"?
|
||||||
|
~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*)
|
||||||
|
~ ("." ~ ASCII_DIGIT*)?
|
||||||
|
~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
|
||||||
|
}
|
||||||
|
|
||||||
|
alpha = { 'a'..'z' | 'A'..'Z' }
|
||||||
|
digit = { '0'..'9' }
|
||||||
|
|
||||||
|
ident = { (alpha | digit | ".")+}
|
||||||
|
version = {digit* ~ "." ~ digit*}
|
||||||
|
|
||||||
|
import = {"import" ~ WHITE_SPACE ~ ident ~ WHITE_SPACE ~ version ~ NEWLINE*}
|
||||||
|
|
||||||
|
property = {WHITE_SPACE* ~ ident ~ ":" ~ WHITE_SPACE* ~ (number|string |ident) ~ NEWLINE* }
|
||||||
|
|
||||||
|
body = {WHITE_SPACE* ~ ident ~ WHITE_SPACE ~ "{" ~ NEWLINE* ~ (property|body)+ ~ NEWLINE* ~ WHITE_SPACE* ~ "}" ~ NEWLINE?}
|
||||||
|
|
||||||
|
qml = {import* ~ NEWLINE* ~ body}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import QtQuick 2.3
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 200
|
||||||
|
height: 500
|
||||||
|
color: "red"
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Hello, Erinn!"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
use specs::Component;
|
||||||
|
use specs::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub struct Item {
|
||||||
|
pub(crate) name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub struct Dimensions {
|
||||||
|
pub(crate) width: f64,
|
||||||
|
pub(crate) height: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
pub struct Text {
|
||||||
|
pub(crate) text: String
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue