images and borders

This commit is contained in:
Sarah Jamie Lewis 2020-07-05 20:45:09 -07:00
parent 15dba79edc
commit f5908ef0d5
15 changed files with 146 additions and 54 deletions

1
Cargo.lock generated
View File

@ -1236,6 +1236,7 @@ dependencies = [
"orbtk",
"pest",
"pest_derive",
"rand 0.6.5",
"rhai",
]

View File

@ -11,4 +11,5 @@ pest = "2.1.3"
pest_derive = "2.1.0"
orbtk = { git = "https://github.com/redox-os/orbtk.git", branch = "develop" }
rhai = "0.16.1"
evmap = "11.0.0-alpha.1"
evmap = "11.0.0-alpha.1"
rand = "0.6.0"

View File

@ -31,7 +31,7 @@ function_code = {
function = {WHITE_SPACE* ~ ident ~ WHITE_SPACE* ~ "=" ~ WHITE_SPACE* ~ "[[" ~ function_code* ~ "]]" ~ NEWLINE* }
property = {WHITE_SPACE* ~ ident ~ ":" ~ WHITE_SPACE* ~ (number|string |ident|function) ~ NEWLINE* }
property = {WHITE_SPACE* ~ ident ~ ":" ~ WHITE_SPACE* ~ (number|string |ident|("[[" ~ function_code* ~ "]]")) ~ NEWLINE* }
body = {WHITE_SPACE* ~ ident ~ WHITE_SPACE ~ "{" ~ NEWLINE* ~ (property|function|body)* ~ NEWLINE* ~ WHITE_SPACE* ~ "}" ~ NEWLINE?}

View File

@ -10,6 +10,14 @@ Grid {
}
Rectangle {
color: "red"
border.color: "#550099"
anchors.centerIn: parent
Image {
id: opimg
anchors.centerIn: parent
opacity: [[rand_opacity()]]
source: "./res/openprivacy.png"
}
}
Rectangle {
color: "red"

BIN
res/openprivacy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -8,12 +8,13 @@ pub mod parser;
pub mod widget_builders;
use crate::parser::QML;
use crate::parser::{parse_qml, Value};
use crate::widget_builders::QmlWidgetBuilder;
use crate::widget_builders::{QmlWidgetBuilder, QmlContext};
use evmap::{ReadHandle, WriteHandle};
use std::borrow::BorrowMut;
use std::collections::VecDeque;
use std::sync::mpsc;
use rand::Rng;
#[macro_use]
extern crate pest_derive;
@ -39,8 +40,9 @@ impl Widget for MainViewState {
let (r, w) = evmap::new();
let mut ids = vec![];
let this = QmlWidgetBuilder::new().build(widget, 0, 0, top_level[0].0.clone(), top_level[0].1.clone(), ctx, ids.borrow_mut()); //render_ctx(widget, ctx, &top_level, 0, 0, ids.borrow_mut()).unwrap();
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_state(
this,
Box::new(MVState {
@ -48,7 +50,7 @@ impl Widget for MainViewState {
rx: Some(rxf),
engine: Engine::new(),
codes: VecDeque::new(),
ids: ids.clone(),
ids: qmlctx.clone(),
value_map: (None, Some(w)),
}),
);
@ -63,7 +65,7 @@ impl Widget for MainViewState {
tx: Some(txf),
engine: Engine::new(),
codes: codes,
ids: ids.clone(),
ids: qmlctx.clone(),
value_map: (Some(r), None),
}),
);
@ -85,7 +87,7 @@ pub struct MVState {
pub tx: Option<Sender<(String, String, String)>>,
pub rx: Option<Receiver<(String, String, String)>>,
pub codes: VecDeque<String>,
pub ids: Vec<String>,
pub ids: QmlContext,
pub value_map: (Option<ReadHandle<String, String>>, Option<WriteHandle<String, String>>),
}
@ -122,13 +124,31 @@ impl State for MVState {
fn update(&mut self, _registry: &mut Registry, ctx: &mut Context) {
match self.value_map.1.borrow_mut() {
Some(w) => {
for id in self.ids.iter() {
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());
self.engine.register_fn("rand_opacity", move || -> (f32) {
let mut rng = rand::thread_rng();
rng.gen_range(0.0,1.0) as f32
});
for ((entity, property), code) in self.ids.code.iter() {
let result = self.engine.eval::<(f32)>(code.as_str());
let point = result.unwrap();
println!("{}.{} = {} {:?}", entity, property, code, point);
ctx.child(entity.as_str()).set::<f32>(property, point);
}
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());
}
w.update(id.clone() + ".text", res.as_string());
}
w.refresh();
}

View File

@ -71,7 +71,12 @@ fn parse(qml: Pairs<Rule>) -> QML {
println!("Found new Property: {} {}", ident, value.as_str());
qmldoc.properties.insert(String::from(ident), QmlIdent(String::from(value.as_str())));
}
_ => {}
_ => {
println!("Found new Property: {} {:?}", ident, value.as_rule());
let value = String::from(value.as_str()) + tokens.concat().as_ref();
println!("Found new Property: {} {}", ident, value.as_str());
qmldoc.properties.insert(String::from(ident), QmlString(String::from(value.clone().trim())));
}
}
}
Rule::function => {

View File

@ -1,7 +1,7 @@
use crate::parser::Value::{QmlIdent, QmlString};
use crate::parser::{Value, QML};
use crate::state;
use crate::widget_builders::WidgetBuilder;
use crate::widget_builders::{WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -9,7 +9,7 @@ use orbtk::Entity;
pub struct ButtonBuilder {}
impl WidgetBuilder for ButtonBuilder {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |id, ctx, row, col, _ids| -> Entity {
let mut button = Button::new();
button = button.attach(Grid::row(row as usize));

View File

@ -1,5 +1,5 @@
use crate::parser::{Value, QML};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -7,8 +7,8 @@ use orbtk::Entity;
pub struct GridBuilder {}
impl WidgetBuilder for GridBuilder {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
return Box::new(move |id, ctx, row, col, ids| -> Entity {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |id, ctx, row, col, qmlctx| -> Entity {
let mut grid = Grid::new();
grid = grid.attach(Grid::row(row as usize));
grid = grid.attach(Grid::column(col as usize));
@ -32,7 +32,7 @@ impl WidgetBuilder for GridBuilder {
//rect = rect.attach(Grid::column(gcol as usize));
let qwb = QmlWidgetBuilder::new();
for (child_type, child_qml) in children.iter() {
grid = grid.child(qwb.build(id, grow as usize, gcol as usize, child_type.clone(), child_qml.clone(), ctx, ids));
grid = grid.child(qwb.build(id, grow as usize, gcol as usize, child_type.clone(), child_qml.clone(), ctx, qmlctx));
grow += 1;
if grow as u32 == rows {
grow = 0;

View File

@ -0,0 +1,44 @@
use crate::parser::Value::{QmlIdent, QmlString};
use crate::parser::{Value, QML};
use crate::state;
use crate::widget_builders::{WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
pub struct ImageBuilder {}
impl WidgetBuilder for ImageBuilder {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |id, ctx, row, col, qmlctx| -> Entity {
let mut image = ImageWidget::new();
image = image.attach(Grid::row(row as usize));
image = image.attach(Grid::column(col as usize));
let widget_id = match properties.get("id") {
Some(QmlIdent(text)) => {
image = image.id(text.clone());
qmlctx.indexes.push(text.clone());
text.clone()
}
_ => String::new()
};
let src = match properties.get("source") {
Some(QmlString(src)) => src.clone(),
_ => String::new(),
};
image = image.image(src);
match properties.get("anchors.centerIn") {
Some(QmlIdent(str)) => {
if str.eq("parent") {
image = image.v_align(Alignment::Center);
image = image.h_align(Alignment::Center);
}
}
_ => {}
}
return image.build(ctx);
});
}
}

View File

@ -1,6 +1,6 @@
use crate::parser::Value::QmlString;
use crate::parser::{parse_qml, Value, QML};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -11,12 +11,12 @@ pub struct ImportBuilder {
}
impl WidgetBuilder for ImportBuilder {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
let import_source = self.source.clone();
return Box::new(move |id, ctx, row, col, ids| -> Entity {
return Box::new(move |id, ctx, row, col, qmlctx| -> Entity {
let qml_doc = parse_qml(format!("./res/{}.qml", import_source).as_str());
let top_level = qml_doc.children.clone();
QmlWidgetBuilder::new().build(id, 0, 0, top_level[0].0.clone(), top_level[0].1.clone(), ctx, ids.borrow_mut())
QmlWidgetBuilder::new().build(id, 0, 0, top_level[0].0.clone(), top_level[0].1.clone(), ctx, qmlctx.borrow_mut())
});
}
}

View File

@ -1,4 +1,4 @@
use crate::parser::Value::QmlNumber;
use crate::parser::Value::{QmlNumber, QmlString};
use crate::parser::{Value, QML};
use crate::widget_builders::button::ButtonBuilder;
use crate::widget_builders::grid::GridBuilder;
@ -10,6 +10,7 @@ use orbtk::Entity;
use crate::widget_builders::import::ImportBuilder;
use std::collections::HashMap;
use crate::widget_builders::image::ImageBuilder;
pub mod button;
pub mod grid;
@ -17,6 +18,18 @@ pub mod import;
pub mod rectangle;
pub mod textedit;
pub mod textfield;
pub mod image;
pub fn parse_color_property(properties: &HashMap<String,Value>, prop: &str) -> Color {
match properties.get(prop) {
Some(QmlString(col)) => match col.as_str() {
"red" => Color::rgb(0xff, 00, 00),
"blue" => Color::rgb(0x00, 00, 0xff),
_ => Color::from(col.as_str()),
},
_ => Color::rgb(0xff, 0xff, 0xff),
}
}
fn parse_number(val: Option<&Value>) -> f64 {
match val {
@ -25,8 +38,14 @@ fn parse_number(val: Option<&Value>) -> f64 {
}
}
#[derive(Clone)]
pub struct QmlContext{
pub(crate) indexes: Vec<String>,
pub(crate) code: HashMap<(String, String),String>
}
pub trait WidgetBuilder {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity>;
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity>;
}
pub struct QmlWidgetBuilder {
@ -41,21 +60,22 @@ impl QmlWidgetBuilder {
qwb.widgets.insert(String::from("Text"), Box::new(TextBuilder {}));
qwb.widgets.insert(String::from("TextField"), Box::new(TextEditBuilder {}));
qwb.widgets.insert(String::from("Button"), Box::new(ButtonBuilder {}));
qwb.widgets.insert(String::from("Image"), Box::new(ImageBuilder {}));
qwb
}
pub fn build(&self, id: Entity, row: usize, col: usize, widget_type: String, qml: QML, ctx: &mut BuildContext, ids: &mut Vec<String>) -> Entity {
pub fn build(&self, id: Entity, row: usize, col: usize, widget_type: String, qml: QML, ctx: &mut BuildContext, qmlctx: &mut QmlContext) -> Entity {
match self.widgets.get(&widget_type) {
Some(builder) => {
let wfn = builder.build(qml.properties, qml.children);
let widget = wfn(id, ctx, row, col, ids);
let widget = wfn(id, ctx, row, col, qmlctx);
return widget;
}
_ => {
let builder = ImportBuilder { source: widget_type };
let wfn = builder.build(qml.properties, qml.children);
let widget = wfn(id, ctx, row, col, ids);
let widget = wfn(id, ctx, row, col, qmlctx);
return widget;
}
}

View File

@ -1,6 +1,6 @@
use crate::parser::Value::QmlString;
use crate::parser::{Value, QML};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder};
use crate::widget_builders::{parse_number, QmlWidgetBuilder, WidgetBuilder, QmlContext, parse_color_property};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -8,30 +8,23 @@ use orbtk::Entity;
pub struct RectangleBuilder {}
impl WidgetBuilder for RectangleBuilder {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
return Box::new(move |id, ctx, row, col, ids| -> Entity {
fn build(&self, properties: HashMap<String, Value>, children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |id, ctx, row, col, qmlctx| -> Entity {
let _width = parse_number(properties.get("width"));
let _height = parse_number(properties.get("height"));
let color = match properties.get("color") {
Some(QmlString(col)) => match col.as_str() {
"red" => Color::rgb(0xff, 00, 00),
"blue" => Color::rgb(0x00, 00, 0xff),
_ => Color::rgb(0xff, 0xff, 0xff),
},
_ => Color::rgb(0xff, 0xff, 0xff),
};
let mut rect = Container::new()
// .width(width)
// .height(height)
.background(color);
let mut rect = Container::new();
rect = rect.background(parse_color_property(&properties, "color"));
rect = rect.border_brush(parse_color_property(&properties, "border.color"));
rect = rect.border_width(Thickness::new(1.0,1.0,1.0,1.0));
rect = rect.attach(Grid::row(row as usize));
rect = rect.attach(Grid::column(col as usize));
let qwb = QmlWidgetBuilder::new();
for (child_type, child_qml) in children.iter() {
rect = rect.child(qwb.build(id, 0, 0, child_type.clone(), child_qml.clone(), ctx, ids));
rect = rect.child(qwb.build(id, 0, 0, child_type.clone(), child_qml.clone(), ctx, qmlctx));
}
return rect.build(ctx);
});
}

View File

@ -1,7 +1,7 @@
use crate::parser::Value::{QmlIdent, QmlString};
use crate::parser::{Value, QML};
use crate::state;
use crate::widget_builders::WidgetBuilder;
use crate::widget_builders::{WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -9,8 +9,8 @@ use orbtk::Entity;
pub struct TextEditBuilder {}
impl WidgetBuilder for TextEditBuilder {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
return Box::new(move |id, ctx, row, col, ids| -> Entity {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |id, ctx, row, col, qmlctx| -> Entity {
let text = match properties.get("text") {
Some(QmlString(text)) => text.clone(),
_ => String::new(),
@ -25,7 +25,7 @@ impl WidgetBuilder for TextEditBuilder {
match properties.get("id") {
Some(QmlIdent(text)) => {
tt = tt.id(text.clone());
ids.push(text.clone())
qmlctx.indexes.push(text.clone())
}
_ => {}
};

View File

@ -1,6 +1,6 @@
use crate::parser::Value::{QmlIdent, QmlString};
use crate::parser::{Value, QML};
use crate::widget_builders::WidgetBuilder;
use crate::widget_builders::{WidgetBuilder, QmlContext};
use orbtk::prelude::HashMap;
use orbtk::prelude::*;
use orbtk::Entity;
@ -8,8 +8,8 @@ use orbtk::Entity;
pub struct TextBuilder {}
impl WidgetBuilder for TextBuilder {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut Vec<String>) -> Entity> {
return Box::new(move |_id, ctx, row, col, ids| -> Entity {
fn build(&self, properties: HashMap<String, Value>, _children: Vec<(String, QML)>) -> Box<dyn Fn(Entity, &mut BuildContext, usize, usize, &mut QmlContext) -> Entity> {
return Box::new(move |_id, ctx, row, col, qmlctx| -> Entity {
let text = match properties.get("text") {
Some(QmlString(text)) => text.clone(),
_ => String::new(),
@ -23,7 +23,7 @@ impl WidgetBuilder for TextBuilder {
match properties.get("id") {
Some(QmlIdent(text)) => {
tt = tt.id(text.clone());
ids.push(text.clone())
qmlctx.indexes.push(text.clone())
}
_ => {}
};