mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-09 20:06:18 +00:00
Viewer: Use corelib::rtti::PropertyInfo for declared property
This commit is contained in:
parent
c024f97890
commit
2debdb43ed
2 changed files with 38 additions and 86 deletions
|
@ -2,6 +2,7 @@ use corelib::{abi::datastructures::ItemRef, EvaluationContext, SharedString};
|
||||||
use sixtyfps_compiler::expression_tree::Expression;
|
use sixtyfps_compiler::expression_tree::Expression;
|
||||||
use sixtyfps_compiler::typeregister::Type;
|
use sixtyfps_compiler::typeregister::Type;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
pub trait ErasedPropertyInfo {
|
pub trait ErasedPropertyInfo {
|
||||||
fn get(&self, item: ItemRef, context: &EvaluationContext) -> Value;
|
fn get(&self, item: ItemRef, context: &EvaluationContext) -> Value;
|
||||||
fn set(&self, item: ItemRef, value: Value);
|
fn set(&self, item: ItemRef, value: Value);
|
||||||
|
@ -76,7 +77,9 @@ pub fn eval_expression(
|
||||||
let element = element.upgrade().unwrap();
|
let element = element.upgrade().unwrap();
|
||||||
if element.borrow().id == component.root_element.borrow().id {
|
if element.borrow().id == component.root_element.borrow().id {
|
||||||
if let Some(x) = ctx.custom_properties.get(name) {
|
if let Some(x) = ctx.custom_properties.get(name) {
|
||||||
return unsafe { (x.get)(ctx.mem.offset(x.offset as isize), &eval_context) };
|
return unsafe {
|
||||||
|
x.prop.get(&*ctx.mem.offset(x.offset as isize), &eval_context).unwrap()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let item_info = &ctx.items[element.borrow().id.as_str()];
|
let item_info = &ctx.items[element.borrow().id.as_str()];
|
||||||
|
@ -119,8 +122,8 @@ pub fn eval_expression(
|
||||||
if element.borrow().id == component.root_element.borrow().id {
|
if element.borrow().id == component.root_element.borrow().id {
|
||||||
if let Some(x) = ctx.custom_properties.get(name) {
|
if let Some(x) = ctx.custom_properties.get(name) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let p = ctx.mem.offset(x.offset as isize);
|
let p = &*ctx.mem.offset(x.offset as isize);
|
||||||
(x.set)(p, eval((x.get)(p, &eval_context)));
|
x.prop.set(p, eval(x.prop.get(p, &eval_context).unwrap())).unwrap();
|
||||||
}
|
}
|
||||||
return Value::Void;
|
return Value::Void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use core::ptr::NonNull;
|
||||||
use corelib::abi::datastructures::{
|
use corelib::abi::datastructures::{
|
||||||
ComponentBox, ComponentRef, ComponentRefMut, ComponentVTable, ItemVTable,
|
ComponentBox, ComponentRef, ComponentRefMut, ComponentVTable, ItemVTable,
|
||||||
};
|
};
|
||||||
|
use corelib::rtti::PropertyInfo;
|
||||||
use corelib::{EvaluationContext, Property, SharedString};
|
use corelib::{EvaluationContext, Property, SharedString};
|
||||||
use object_tree::Element;
|
use object_tree::Element;
|
||||||
use sixtyfps_compiler::typeregister::Type;
|
use sixtyfps_compiler::typeregister::Type;
|
||||||
|
@ -11,86 +12,16 @@ use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
type SetterFn = unsafe fn(*mut u8, eval::Value);
|
|
||||||
type GetterFn = unsafe fn(*mut u8, &EvaluationContext) -> eval::Value;
|
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[structopt(name = "path to .60 file", parse(from_os_str))]
|
#[structopt(name = "path to .60 file", parse(from_os_str))]
|
||||||
path: std::path::PathBuf,
|
path: std::path::PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait PropertyWriter {
|
|
||||||
unsafe fn write(ptr: *mut u8, value: eval::Value);
|
|
||||||
unsafe fn read(ptr: *mut u8, context: &EvaluationContext) -> eval::Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PropertyWriter for f32 {
|
|
||||||
unsafe fn write(ptr: *mut u8, value: eval::Value) {
|
|
||||||
let val: Self = match value {
|
|
||||||
eval::Value::Number(v) => v as _,
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
(*(ptr as *mut Property<Self>)).set(val);
|
|
||||||
}
|
|
||||||
unsafe fn read(ptr: *mut u8, context: &EvaluationContext) -> eval::Value {
|
|
||||||
let s: Self = (*(ptr as *mut Property<Self>)).get(context);
|
|
||||||
eval::Value::Number(s as _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PropertyWriter for bool {
|
|
||||||
unsafe fn write(_ptr: *mut u8, _value: eval::Value) {
|
|
||||||
todo!("Boolean expression not implemented")
|
|
||||||
}
|
|
||||||
unsafe fn read(_ptr: *mut u8, _context: &EvaluationContext) -> eval::Value {
|
|
||||||
todo!("Boolean expression not implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PropertyWriter for u32 {
|
|
||||||
unsafe fn write(ptr: *mut u8, value: eval::Value) {
|
|
||||||
let val: Self = match value {
|
|
||||||
eval::Value::Number(v) => v as _,
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
(*(ptr as *mut Property<Self>)).set(val);
|
|
||||||
}
|
|
||||||
unsafe fn read(ptr: *mut u8, context: &EvaluationContext) -> eval::Value {
|
|
||||||
let s: Self = (*(ptr as *mut Property<Self>)).get(context);
|
|
||||||
eval::Value::Number(s as _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PropertyWriter for SharedString {
|
|
||||||
unsafe fn write(ptr: *mut u8, value: eval::Value) {
|
|
||||||
let val: Self = match value {
|
|
||||||
eval::Value::String(v) => v,
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
(*(ptr as *mut Property<Self>)).set(val);
|
|
||||||
}
|
|
||||||
unsafe fn read(ptr: *mut u8, context: &EvaluationContext) -> eval::Value {
|
|
||||||
let s: Self = (*(ptr as *mut Property<Self>)).get(context);
|
|
||||||
eval::Value::String(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn construct<T: Default>(ptr: *mut u8) {
|
unsafe fn construct<T: Default>(ptr: *mut u8) {
|
||||||
core::ptr::write(ptr as *mut T, T::default());
|
core::ptr::write(ptr as *mut T, T::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_property<T: PropertyWriter>(ptr: *mut u8, e: eval::Value) {
|
|
||||||
T::write(ptr, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn get_property<T: PropertyWriter>(
|
|
||||||
ptr: *mut u8,
|
|
||||||
context: &EvaluationContext,
|
|
||||||
) -> eval::Value {
|
|
||||||
T::read(ptr, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn dummy_destroy(_: ComponentRefMut) {
|
extern "C" fn dummy_destroy(_: ComponentRefMut) {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
@ -102,7 +33,7 @@ extern "C" fn dummy_create(_: &ComponentVTable) -> ComponentBox {
|
||||||
struct ItemWithinComponent {
|
struct ItemWithinComponent {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
rtti: Rc<RuntimeTypeInfo>,
|
rtti: Rc<RuntimeTypeInfo>,
|
||||||
item: Rc<RefCell<Element>>,
|
elem: Rc<RefCell<Element>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemWithinComponent {
|
impl ItemWithinComponent {
|
||||||
|
@ -118,8 +49,7 @@ mod eval;
|
||||||
|
|
||||||
struct PropertiesWithinComponent {
|
struct PropertiesWithinComponent {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
set: SetterFn,
|
prop: Box<dyn PropertyInfo<u8, eval::Value>>,
|
||||||
get: GetterFn,
|
|
||||||
create: unsafe fn(*mut u8),
|
create: unsafe fn(*mut u8),
|
||||||
}
|
}
|
||||||
pub struct ComponentImpl {
|
pub struct ComponentImpl {
|
||||||
|
@ -209,18 +139,26 @@ fn main() -> std::io::Result<()> {
|
||||||
});
|
});
|
||||||
items_types.insert(
|
items_types.insert(
|
||||||
item.id.clone(),
|
item.id.clone(),
|
||||||
ItemWithinComponent { offset: current_offset, rtti: rt.clone(), item: rc_item.clone() },
|
ItemWithinComponent { offset: current_offset, rtti: rt.clone(), elem: rc_item.clone() },
|
||||||
);
|
);
|
||||||
current_offset += rt.size;
|
current_offset += rt.size;
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut custom_properties = HashMap::new();
|
let mut custom_properties = HashMap::new();
|
||||||
for (name, decl) in &tree.root_component.root_element.borrow().property_declarations {
|
for (name, decl) in &tree.root_component.root_element.borrow().property_declarations {
|
||||||
fn create_and_set<T: PropertyWriter + Default + 'static>(
|
fn create_and_set<T: Clone + Default + 'static>(
|
||||||
) -> (SetterFn, GetterFn, unsafe fn(*mut u8)) {
|
) -> (Box<dyn PropertyInfo<u8, eval::Value>>, unsafe fn(*mut u8))
|
||||||
(set_property::<T>, get_property::<T>, construct::<Property<T>>)
|
where
|
||||||
|
T: std::convert::TryInto<eval::Value>,
|
||||||
|
eval::Value: std::convert::TryInto<T>,
|
||||||
|
{
|
||||||
|
// Fixme: using u8 in PropertyInfo<> is not sound, we would need to materialize a type for out component
|
||||||
|
(
|
||||||
|
Box::new(unsafe { vtable::FieldOffset::<u8, Property<T>>::new_from_offset(0) }),
|
||||||
|
construct::<Property<T>>,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
let (set, get, create) = match decl.property_type {
|
let (prop, create) = match decl.property_type {
|
||||||
Type::Float32 => create_and_set::<f32>(),
|
Type::Float32 => create_and_set::<f32>(),
|
||||||
Type::Int32 => create_and_set::<u32>(),
|
Type::Int32 => create_and_set::<u32>(),
|
||||||
Type::String => create_and_set::<SharedString>(),
|
Type::String => create_and_set::<SharedString>(),
|
||||||
|
@ -232,7 +170,7 @@ fn main() -> std::io::Result<()> {
|
||||||
};
|
};
|
||||||
custom_properties.insert(
|
custom_properties.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
PropertiesWithinComponent { offset: current_offset, set, get, create },
|
PropertiesWithinComponent { offset: current_offset, prop, create },
|
||||||
);
|
);
|
||||||
// FIXME: get the actual size depending of the type
|
// FIXME: get the actual size depending of the type
|
||||||
current_offset += 32;
|
current_offset += 32;
|
||||||
|
@ -260,7 +198,7 @@ fn main() -> std::io::Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let item = item_within_component.item_from_component(mem);
|
let item = item_within_component.item_from_component(mem);
|
||||||
(item_within_component.rtti.construct)(item.as_ptr() as _);
|
(item_within_component.rtti.construct)(item.as_ptr() as _);
|
||||||
let elem = item_within_component.item.borrow();
|
let elem = item_within_component.elem.borrow();
|
||||||
for (prop, expr) in &elem.bindings {
|
for (prop, expr) in &elem.bindings {
|
||||||
let ty = elem.lookup_property(prop.as_str());
|
let ty = elem.lookup_property(prop.as_str());
|
||||||
if ty == Type::Signal {
|
if ty == Type::Signal {
|
||||||
|
@ -281,11 +219,22 @@ fn main() -> std::io::Result<()> {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if let Some(PropertiesWithinComponent { offset, set, .. }) =
|
} else if let Some(PropertiesWithinComponent { offset, prop, .. }) =
|
||||||
ctx.custom_properties.get(prop.as_str())
|
ctx.custom_properties.get(prop.as_str())
|
||||||
{
|
{
|
||||||
|
if expr.is_constant() {
|
||||||
let v = eval::eval_expression(expr, &*ctx, &eval_context);
|
let v = eval::eval_expression(expr, &*ctx, &eval_context);
|
||||||
set(item.as_ptr().add(*offset) as _, v);
|
prop.set(&*item.as_ptr().add(*offset), v).unwrap();
|
||||||
|
} else {
|
||||||
|
let expr = expr.clone();
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
prop.set_binding(
|
||||||
|
&*item.as_ptr().add(*offset),
|
||||||
|
Box::new(move |eval_context| {
|
||||||
|
eval::eval_expression(&expr, &*ctx, eval_context)
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("unkown property {}", prop);
|
panic!("unkown property {}", prop);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue