mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 22:01:13 +00:00

Removed the drop and create from the ComponentVTable: since we are not using VBox<ComponentVTable>, this simplifies a bit the code of the interpreter and everything else. But there is still a lot of changes everywhere to support that the Component is pinned. This is just for the component. Which would be required if later we want to access the properties as Pin<Property<_>>. But we have not yet ability to do projections
124 lines
4.6 KiB
Rust
124 lines
4.6 KiB
Rust
/*!
|
|
# SixtyFPS interpreter library
|
|
|
|
**NOTE:** This library is an internal crate for the SixtyFPS project.
|
|
This crate should not be used directly by application using SixtyFPS.
|
|
You should use the `sixtyfps` crate instead
|
|
*/
|
|
|
|
mod dynamic_component;
|
|
mod dynamic_type;
|
|
mod eval;
|
|
|
|
pub use dynamic_component::load;
|
|
pub use dynamic_component::ComponentDescription;
|
|
pub use eval::Value;
|
|
|
|
pub use dynamic_component::ComponentBox;
|
|
use sixtyfps_corelib::abi::datastructures::{ComponentRef, ComponentRefMut};
|
|
use sixtyfps_corelib::{ComponentRefPin, EvaluationContext, Signal};
|
|
use std::{collections::HashMap, pin::Pin, rc::Rc};
|
|
|
|
impl ComponentDescription {
|
|
/// The name of this Component as written in the .60 file
|
|
pub fn id(&self) -> &str {
|
|
self.original.id.as_str()
|
|
}
|
|
|
|
/// List of publicly declared properties or signal
|
|
pub fn properties(&self) -> HashMap<String, sixtyfps_compilerlib::typeregister::Type> {
|
|
self.original
|
|
.root_element
|
|
.borrow()
|
|
.property_declarations
|
|
.iter()
|
|
.map(|(s, v)| (s.clone(), v.property_type.clone()))
|
|
.collect()
|
|
}
|
|
|
|
/// Instantiate a runtime component from this ComponentDescription
|
|
pub fn create(self: Rc<Self>) -> ComponentBox {
|
|
dynamic_component::instentiate(self, None)
|
|
}
|
|
|
|
/// Set a value to property.
|
|
///
|
|
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
|
|
/// or if the property with this name does not exist in this component
|
|
pub fn set_property(
|
|
&self,
|
|
component: ComponentRefPin,
|
|
name: &str,
|
|
value: Value,
|
|
) -> Result<(), ()> {
|
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
|
return Err(());
|
|
}
|
|
let x = self.custom_properties.get(name).ok_or(())?;
|
|
unsafe { x.prop.set(&*component.as_ptr().add(x.offset), value) }
|
|
}
|
|
|
|
/// Set a binding to a property
|
|
///
|
|
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
|
|
/// or if the property with this name does not exist in this component
|
|
pub fn set_binding(
|
|
&self,
|
|
component: ComponentRef,
|
|
name: &str,
|
|
binding: Box<dyn Fn(&EvaluationContext) -> Value>,
|
|
) -> Result<(), ()> {
|
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
|
return Err(());
|
|
}
|
|
let x = self.custom_properties.get(name).ok_or(())?;
|
|
unsafe { x.prop.set_binding(&*component.as_ptr().add(x.offset), binding) };
|
|
Ok(())
|
|
}
|
|
|
|
/// Return the value of a property
|
|
///
|
|
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
|
|
/// or if a signal with this name does not exist in this component
|
|
pub fn get_property(&self, eval_context: &EvaluationContext, name: &str) -> Result<Value, ()> {
|
|
if !core::ptr::eq((&self.ct) as *const _, eval_context.component.get_vtable() as *const _) {
|
|
return Err(());
|
|
}
|
|
let x = self.custom_properties.get(name).ok_or(())?;
|
|
unsafe { x.prop.get(&*eval_context.component.as_ptr().add(x.offset), eval_context) }
|
|
}
|
|
|
|
/// Sets an handler for a signal
|
|
///
|
|
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
|
|
/// or if the property with this name does not exist in this component
|
|
pub fn set_signal_handler(
|
|
&self,
|
|
component: Pin<ComponentRefMut>,
|
|
name: &str,
|
|
handler: Box<dyn Fn(&EvaluationContext, ())>,
|
|
) -> Result<(), ()> {
|
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
|
return Err(());
|
|
}
|
|
let x = self.custom_signals.get(name).ok_or(())?;
|
|
let sig = unsafe { &mut *(component.as_ptr().add(*x) as *mut Signal<()>) };
|
|
sig.set_handler(handler);
|
|
Ok(())
|
|
}
|
|
|
|
/// Emits the specified signal
|
|
///
|
|
/// Returns an error if the component is not an instance corresponding to this ComponentDescription,
|
|
/// or if the signal with this name does not exist in this component
|
|
pub fn emit_signal(&self, eval_context: &EvaluationContext, name: &str) -> Result<(), ()> {
|
|
let component = eval_context.component;
|
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
|
return Err(());
|
|
}
|
|
let x = self.custom_signals.get(name).ok_or(())?;
|
|
let sig = unsafe { &mut *(component.as_ptr().add(*x) as *mut Signal<()>) };
|
|
sig.emit(eval_context, ());
|
|
Ok(())
|
|
}
|
|
}
|